Former-commit-id:a02aeb236c
[formerly9f19e3f712
] [formerly06a8b51d6d
[formerly 64fa9254b946eae7e61bbc3f513b7c3696c4f54f]] Former-commit-id:06a8b51d6d
Former-commit-id:3360eb6c5f
286 lines
10 KiB
Java
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);
|
|
}
|
|
}
|