awips2/edexOsgi/com.raytheon.edex.utilitysrv/src/com/raytheon/edex/services/LocalizationStreamHandler.java
root 8e80217e59 Initial revision of AWIPS2 11.9.0-7p5
Former-commit-id: a02aeb236c [formerly 9f19e3f712] [formerly 06a8b51d6d [formerly 64fa9254b946eae7e61bbc3f513b7c3696c4f54f]]
Former-commit-id: 06a8b51d6d
Former-commit-id: 3360eb6c5f
2012-01-06 08:55:05 -06:00

286 lines
10 KiB
Java

/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.edex.services;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import com.raytheon.edex.utility.ProtectedFiles;
import com.raytheon.uf.common.auth.user.IUser;
import com.raytheon.uf.common.localization.FileUpdatedMessage;
import com.raytheon.uf.common.localization.FileUpdatedMessage.FileChangeType;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.localization.exception.LocalizationException;
import com.raytheon.uf.common.localization.stream.AbstractLocalizationStreamRequest;
import com.raytheon.uf.common.localization.stream.LocalizationStreamGetRequest;
import com.raytheon.uf.common.localization.stream.LocalizationStreamPutRequest;
import com.raytheon.uf.edex.auth.resp.AuthorizationResponse;
import com.raytheon.uf.edex.core.EDEXUtil;
/**
* Base handler for localization streaming requests. Delegates work off to a
* get/put handler
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 11, 2010 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class LocalizationStreamHandler
extends
AbstractPrivilegedLocalizationRequestHandler<AbstractLocalizationStreamRequest> {
private class Pair {
LocalizationContext context;
String fileName;
private Pair(LocalizationContext context, String fileName) {
this.context = context;
this.fileName = fileName;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result
+ ((context == null) ? 0 : context.hashCode());
result = prime * result
+ ((fileName == null) ? 0 : fileName.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Pair other = (Pair) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (context == null) {
if (other.context != null)
return false;
} else if (!context.equals(other.context))
return false;
if (fileName == null) {
if (other.fileName != null)
return false;
} else if (!fileName.equals(other.fileName))
return false;
return true;
}
private LocalizationStreamHandler getOuterType() {
return LocalizationStreamHandler.this;
}
}
private Map<Pair, File> fileMap = new HashMap<Pair, File>();
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.serialization.comm.IRequestHandler#handleRequest
* (com.raytheon.uf.common.serialization.comm.IServerRequest)
*/
@Override
public Object handleRequest(AbstractLocalizationStreamRequest request)
throws Exception {
Pair pair = new Pair(request.getContext(), request.getFileName());
File file = fileMap.get(pair);
if (file == null) {
file = PathManagerFactory.getPathManager().getFile(
request.getContext(), request.getFileName());
if (file == null) {
throw new LocalizationException("File with name, "
+ request.getFileName() + ", and context, "
+ String.valueOf(request.getContext())
+ ", could not be found");
}
fileMap.put(pair, file);
}
if (request instanceof LocalizationStreamGetRequest) {
return handleStreamingGet((LocalizationStreamGetRequest) request,
file);
} else if (request instanceof LocalizationStreamPutRequest) {
LocalizationStreamPutRequest req = (LocalizationStreamPutRequest) request;
LocalizationLevel protectedLevel = ProtectedFiles
.getProtectedLevel(req.getLocalizedSite(), request
.getContext().getLocalizationType(), request
.getFileName());
if (protectedLevel != null
&& protectedLevel != request.getContext()
.getLocalizationLevel()) {
throw new LocalizationException("File: "
+ request.getContext().getLocalizationType().toString()
.toLowerCase() + File.separator
+ request.getFileName()
+ " is protected and cannot be overridden");
}
return handleStreamingPut((LocalizationStreamPutRequest) request,
file);
} else {
throw new LocalizationException("Request type of "
+ request.getClass() + " is not recognized");
}
}
private Object handleStreamingGet(LocalizationStreamGetRequest request,
File file) throws Exception {
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(file);
int bytesSkipped = 0;
int toSkip = request.getOffset();
// we are done if we the toSkip is 0, or toSkip increased in size
while ((toSkip != 0) && (toSkip <= request.getOffset())) {
bytesSkipped += inputStream.skip(toSkip);
toSkip = request.getOffset() - bytesSkipped;
}
if (toSkip != 0) {
throw new LocalizationException("Error skipping through file");
}
LocalizationStreamPutRequest response = new LocalizationStreamPutRequest();
byte[] bytes = new byte[request.getNumBytes()];
int bytesRead = inputStream.read(bytes, 0, request.getNumBytes());
if (bytesRead == -1) {
response.setBytes(new byte[0]);
response.setEnd(true);
} else {
if (bytesRead != bytes.length) {
bytes = Arrays.copyOf(bytes, bytesRead);
}
response.setBytes(bytes);
response.setEnd(request.getOffset() + bytesRead == file
.length());
}
return response;
} finally {
if (inputStream != null) {
inputStream.close();
}
}
}
private Object handleStreamingPut(LocalizationStreamPutRequest request,
File file) throws Exception {
if (file.getParentFile().exists() == false) {
file.getParentFile().mkdirs();
}
File tmpFile = new File(file.getParentFile(), file.getName() + "."
+ request.getId());
if ((tmpFile.exists() == false) && (request.getOffset() != 0)) {
throw new LocalizationException(
"Illegal state, request has offset set but file "
+ "has not begun being written to yet.");
} else if (tmpFile.exists()
&& (tmpFile.length() != request.getOffset())) {
throw new LocalizationException(
"Illegal state, request's offset does not match size of file, size = "
+ tmpFile.length() + " offset = "
+ request.getOffset());
}
// if start of request, delete existing temporary file
if (request.getOffset() == 0) {
tmpFile.delete();
}
// if (
if (tmpFile.exists() == false) {
tmpFile.createNewFile();
}
FileOutputStream outputStream = null;
Integer bytesWritten = 0;
try {
outputStream = new FileOutputStream(tmpFile, true);
byte[] bytes = request.getBytes();
bytesWritten += bytes.length;
outputStream.write(bytes);
} finally {
if (outputStream != null) {
outputStream.flush();
outputStream.close();
}
}
if (request.isEnd()) {
FileChangeType changeType = FileChangeType.UPDATED;
if (!file.exists()) {
changeType = FileChangeType.ADDED;
}
tmpFile.renameTo(file);
// tmpFile.delete();
EDEXUtil.getMessageProducer().sendAsync(
UtilityManager.NOTIFY_ID,
new FileUpdatedMessage(request.getContext(), request
.getFileName(), changeType));
}
return bytesWritten;
}
@Override
public AuthorizationResponse authorized(IUser user,
AbstractLocalizationStreamRequest request) {
if (request instanceof LocalizationStreamGetRequest) {
// All gets are authorized
return new AuthorizationResponse(true);
} else if (request instanceof LocalizationStreamPutRequest) {
LocalizationContext context = request.getContext();
LocalizationLevel level = context.getLocalizationLevel();
String fileName = request.getFileName();
return getAuthorizationResponse(user, context, level, fileName,
request.getMyContextName());
}
return new AuthorizationResponse(true);
}
}