| package org.eclipse.emf.emfstore.jax.common; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.ObjectInputStream; |
| import java.io.OutputStream; |
| import java.io.Serializable; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.ws.rs.WebApplicationException; |
| import javax.ws.rs.core.Response; |
| import javax.ws.rs.core.StreamingOutput; |
| |
| import org.apache.commons.lang.SerializationUtils; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.emf.ecore.xmi.XMLResource; |
| import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl; |
| import org.eclipse.emf.emfstore.internal.common.model.IdEObjectCollection; |
| import org.eclipse.emf.emfstore.internal.common.model.util.ModelUtil; |
| import org.eclipse.emf.emfstore.internal.server.exceptions.AccessControlException; |
| import org.eclipse.emf.emfstore.internal.server.exceptions.ClientVersionOutOfDateException; |
| import org.eclipse.emf.emfstore.internal.server.exceptions.ConnectionException; |
| import org.eclipse.emf.emfstore.internal.server.exceptions.FileNotOnServerException; |
| import org.eclipse.emf.emfstore.internal.server.exceptions.FileTransferException; |
| import org.eclipse.emf.emfstore.internal.server.exceptions.InvalidInputException; |
| import org.eclipse.emf.emfstore.internal.server.exceptions.InvalidProjectIdException; |
| import org.eclipse.emf.emfstore.internal.server.exceptions.InvalidVersionSpecException; |
| import org.eclipse.emf.emfstore.internal.server.exceptions.SerializationException; |
| import org.eclipse.emf.emfstore.internal.server.exceptions.ServerKeyStoreException; |
| import org.eclipse.emf.emfstore.internal.server.exceptions.SessionTimedOutException; |
| import org.eclipse.emf.emfstore.internal.server.exceptions.StorageException; |
| import org.eclipse.emf.emfstore.internal.server.exceptions.UnknownSessionException; |
| import org.eclipse.emf.emfstore.internal.server.filetransfer.FileChunk; |
| import org.eclipse.emf.emfstore.internal.server.filetransfer.FileTransferInformation; |
| import org.eclipse.emf.emfstore.internal.server.model.FileIdentifier; |
| import org.eclipse.emf.emfstore.internal.server.model.ModelFactory; |
| import org.eclipse.emf.emfstore.internal.server.model.ProjectId; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.PrimaryVersionSpec; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.TagVersionSpec; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.VersioningFactory; |
| import org.eclipse.emf.emfstore.server.exceptions.ESException; |
| import org.eclipse.emf.emfstore.server.exceptions.ESUpdateRequiredException; |
| |
| /** |
| * helper class with methods for Serialization & Deserialization |
| * |
| * @author Pascal Schliski |
| * |
| */ |
| @SuppressWarnings("restriction") |
| public final class TransferUtil { |
| |
| private static final Integer FLUSH_THRESHOLD = Integer.valueOf(1024); |
| private static final String EXCEPTION_MESSAGE_SEPERATOR = "\n"; //$NON-NLS-1$ |
| |
| /** |
| * Private constructor. |
| */ |
| private TransferUtil() { |
| // private constructor since util class |
| } |
| |
| /** |
| * converts a {@link java.io.Serializable} into a {@link StreamingOutput} |
| * |
| * @param s the {@link java.io.Serializable} |
| * @return the {@link StreamingOutput} |
| */ |
| public static StreamingOutput convertSerializableIntoStreamingOutput(final Serializable s) { |
| |
| final StreamingOutput streamingOutput = new StreamingOutput() { |
| |
| public void write(OutputStream output) throws IOException, |
| WebApplicationException { |
| |
| SerializationUtils.serialize(s, output); |
| } |
| }; |
| return streamingOutput; |
| } |
| |
| /** |
| * get a {@link FileChunk} instance from an {@link InputStream} |
| * |
| * @param is the InputStream |
| * @return the FileChunk object |
| * @throws ClassNotFoundException |
| * @throws IOException |
| */ |
| public static FileChunk getFileChunkFromInputStream(final InputStream is) throws ClassNotFoundException, |
| IOException { |
| final FileChunk fileChunk = (FileChunk) new ObjectInputStream(is).readObject(); |
| return fileChunk; |
| } |
| |
| /** |
| * get a {@link FileChunk} instance from an {@link Response} |
| * |
| * @param response the Response object |
| * @return the FileChunk object |
| * @throws ClassNotFoundException |
| * @throws IOException |
| */ |
| public static FileChunk getFileChunkFromResponse(final Response response) throws ClassNotFoundException, |
| IOException { |
| final InputStream is = response.readEntity(InputStream.class); |
| return getFileChunkFromInputStream(is); |
| } |
| |
| /** |
| * get a {@link FileTransferInformation} from a {@link Response} |
| * |
| * @param response the Response object |
| * @return the FileTransferInformation object |
| * @throws ClassNotFoundException |
| * @throws IOException |
| */ |
| public static FileTransferInformation getFileTransferInformationFromResponse( |
| final Response response) throws ClassNotFoundException, IOException { |
| |
| final InputStream is = response.readEntity(InputStream.class); |
| final FileTransferInformation fileTransferInformation = (FileTransferInformation) new ObjectInputStream(is) |
| .readObject(); |
| return fileTransferInformation; |
| |
| } |
| |
| /** |
| * convert a collection of {@link EObject} into a {@link StreamingOutput} |
| * |
| * @param eObjects |
| * @return the StreamingOutput |
| */ |
| public static StreamingOutput convertEObjectsToXmlIntoStreamingOutput( |
| final Collection<? extends EObject> eObjects) { |
| // convert the list into XML and write it to a StreamingOutput |
| final ResourceSetImpl resourceSetImpl = new ResourceSetImpl(); |
| final XMIResourceImpl resource = (XMIResourceImpl) resourceSetImpl |
| .createResource(ModelUtil.VIRTUAL_URI); |
| |
| resource.setIntrinsicIDToEObjectMap(new HashMap<String, EObject>()); |
| |
| for (final EObject e : eObjects) { |
| EObject copy; |
| if (e instanceof IdEObjectCollection) { |
| copy = ModelUtil.copyIdEObjectCollection((IdEObjectCollection) e, resource); |
| } else { |
| copy = EcoreUtil.copy(e); |
| } |
| |
| resource.getContents().add(copy); |
| } |
| |
| final Map<String, Object> options = new HashMap<String, Object>(); |
| options.put(XMLResource.OPTION_FLUSH_THRESHOLD, FLUSH_THRESHOLD); |
| |
| final StreamingOutput streamingOutput = new StreamingOutput() { |
| |
| public void write(OutputStream output) throws IOException, |
| WebApplicationException { |
| |
| resource.doSave(output, options); |
| |
| } |
| }; |
| return streamingOutput; |
| } |
| |
| /** |
| * convert a single {@link EObject} into a {@link StreamingOutput} |
| * |
| * @param eObject |
| * @return the StreamingOutput |
| */ |
| public static <T extends EObject> StreamingOutput convertEObjectToXmlIntoStreamingOutput( |
| final T eObject) { |
| |
| final List<T> eObjects = new ArrayList<T>(); |
| eObjects.add(eObject); |
| return convertEObjectsToXmlIntoStreamingOutput(eObjects); |
| } |
| |
| /** |
| * converts an {@link InputStream} into a list of {@link EObject}, for example: List<ProjectInfo>, List<BranchInfo>, |
| * ... |
| * |
| * @param is the InputStream |
| * @return the list of EObjects |
| * @throws ESException |
| */ |
| @SuppressWarnings("unchecked") |
| public static <T extends EObject> List<T> getEObjectListFromInputStream( |
| final InputStream is) throws ESException { |
| // create XMLResource and read the entity |
| final ResourceSetImpl resourceSetImpl = new ResourceSetImpl(); |
| final XMIResourceImpl resource = (XMIResourceImpl) resourceSetImpl.createResource(ModelUtil.VIRTUAL_URI); |
| |
| resource.setIntrinsicIDToEObjectMap(new HashMap<String, EObject>()); |
| |
| final List<T> eObjectList = new ArrayList<T>(); |
| try { |
| // create the List<ProjectInfo> from the input stream |
| final Map<String, Object> options = new HashMap<String, Object>(); |
| options.put(XMLResource.OPTION_FLUSH_THRESHOLD, FLUSH_THRESHOLD); |
| resource.doLoad(is, options); |
| for (final Object o : resource.getContents()) { |
| // copy not necessary, no side effects here |
| |
| if (o instanceof IdEObjectCollection) { |
| final IdEObjectCollection collection = (IdEObjectCollection) o; |
| final Map<EObject, String> eObjectToIdMap = new LinkedHashMap<EObject, String>(); |
| final Map<String, EObject> idToEObjectMap = new LinkedHashMap<String, EObject>(); |
| |
| for (final EObject modelElement : collection.getAllModelElements()) { |
| String modelElementId; |
| if (ModelUtil.isIgnoredDatatype(modelElement)) { |
| // create random ID for generic types, won't get serialized |
| // anyway |
| modelElementId = org.eclipse.emf.emfstore.internal.common.model.ModelFactory.eINSTANCE |
| .createModelElementId().getId(); |
| } else { |
| modelElementId = resource.getID(modelElement); |
| } |
| |
| if (modelElementId == null) { |
| throw new ESException("Failed to retrieve ID for EObject contained in project: " //$NON-NLS-1$ |
| + modelElement); |
| } |
| |
| eObjectToIdMap.put(modelElement, modelElementId); |
| idToEObjectMap.put(modelElementId, modelElement); |
| } |
| |
| collection.initMapping(eObjectToIdMap, idToEObjectMap); |
| } |
| |
| eObjectList.add((T) o); |
| } |
| resource.getContents().clear(); |
| |
| } catch (final IOException ex) { |
| ModelUtil.logException(ex); |
| } |
| return eObjectList; |
| } |
| |
| /** |
| * converts an {@link InputStream} to a single {@link EObject} |
| * |
| * @param is the InputStream |
| * @return the EObject |
| * @throws ESException |
| */ |
| public static <T extends EObject> T getEObjectFromInputStream( |
| final InputStream is) throws ESException { |
| |
| final List<T> eObjectListFromInputStream = getEObjectListFromInputStream(is); |
| |
| return eObjectListFromInputStream.get(0); |
| } |
| |
| /** |
| * converts an {@link InputStream} to a list of {@link EObject}, for example: List<ProjectInfo>, List<BranchInfo>, |
| * ... |
| * |
| * @param response the Response |
| * @return the list of EObjects |
| * @throws ESException |
| */ |
| public static <T extends EObject> List<T> getEObjectListFromResponse( |
| final Response response) throws ESException { |
| |
| final InputStream is = response.readEntity(InputStream.class); |
| |
| return getEObjectListFromInputStream(is); |
| } |
| |
| /** |
| * converts an {@link InputStream} to a single {@link EObject} |
| * |
| * @param response the Response |
| * @return the EObject |
| * @throws ESException |
| */ |
| public static <T extends EObject> T getEObjectFromResponse( |
| final Response response) throws ESException { |
| |
| final List<T> eObjectListFromResponse = getEObjectListFromResponse(response); |
| |
| return eObjectListFromResponse.get(0); |
| |
| } |
| |
| /** |
| * convert a String representing the id of a {@link ProjectId} into a {@link ProjectId} |
| * |
| * @param projectIdAsString |
| * @return the ProjectId |
| */ |
| public static ProjectId createProjectIdFromString(String projectIdAsString) { |
| |
| final ProjectId projectId = ModelFactory.eINSTANCE.createProjectId(); |
| projectId.setId(projectIdAsString); |
| return projectId; |
| } |
| |
| /** |
| * create a {@link PrimaryVersionSpec} from a String representing it |
| * |
| * @param sourceVersionSpecAsString |
| * @return the PrimaryVersionSpec |
| */ |
| public static PrimaryVersionSpec createPrimaryVersionSpecFromString(String sourceVersionSpecAsString) { |
| |
| final PrimaryVersionSpec source = VersioningFactory.eINSTANCE.createPrimaryVersionSpec(); |
| source.setIdentifier(Integer.valueOf(sourceVersionSpecAsString)); |
| return source; |
| } |
| |
| /** |
| * convert a String representing a {@link TagVersionSpec} into the {@link TagVersionSpec} |
| * |
| * @param tagVersionSpecAsString |
| * @return the TagVersionSpec |
| */ |
| public static TagVersionSpec createTagVersionSpecFromString(String tagVersionSpecAsString) { |
| final TagVersionSpec tagVersionSpec = VersioningFactory.eINSTANCE.createTagVersionSpec(); |
| tagVersionSpec.setName(tagVersionSpecAsString); |
| return tagVersionSpec; |
| } |
| |
| /** |
| * convert a String into its representing {@link FileIdentifier} |
| * |
| * @param fileIdentifierAsString |
| * @return the FileIdentifier |
| */ |
| public static FileIdentifier createFileIdentifierFromString(String fileIdentifierAsString) { |
| final FileIdentifier fileIdentifier = ModelFactory.eINSTANCE.createFileIdentifier(); |
| fileIdentifier.setIdentifier(fileIdentifierAsString); |
| return fileIdentifier; |
| } |
| |
| /** |
| * create the Response entity message for an {@link ESException} {@link Response} |
| * |
| * @param exception the ESException |
| * @return the Response String |
| */ |
| public static String createResponseMessageForExceptionResponse(ESException exception) { |
| String exceptionMessage = exception.getMessage(); |
| if (exceptionMessage == null || exceptionMessage.isEmpty()) { |
| exceptionMessage = " "; //$NON-NLS-1$ |
| } |
| final String message = exception.getClass().getName() + EXCEPTION_MESSAGE_SEPERATOR + exceptionMessage; |
| return message; |
| } |
| |
| /** |
| * get the class name and message of the exception that the response entity is describing. the entity was created |
| * with createResponseMessageForExceptionResponse(ESException exception) |
| * |
| * @param entity the response entity which was created by TransferUtil.createResponseMessageForExceptionResponse() |
| * @return the {@link ESException} that the entity has represented, null if no match possible |
| */ |
| public static ESException getExceptionFromExceptionResponse(String entity) { |
| |
| if (entity == null || !entity.contains(EXCEPTION_MESSAGE_SEPERATOR)) { |
| return null; |
| } |
| |
| final String[] strings = entity.split(EXCEPTION_MESSAGE_SEPERATOR); |
| |
| if (strings.length != 2) { |
| return null; |
| } |
| |
| final String className = strings[0]; |
| final String message = strings[1]; |
| |
| return getSpecificESException(className, message); |
| } |
| |
| /** |
| * create a subclass of {@link ESException} from the given className |
| * |
| * @param className the type of ESException that should be returned |
| * @param message the message of the Exception. can be null |
| * @return the subclass instance |
| */ |
| private static ESException getSpecificESException(String className, String message) { |
| |
| // check the class type of the ESException and return it with its message |
| if (className.equals(AccessControlException.class.getName())) { |
| return new AccessControlException(message); |
| } |
| if (className.equals(ClientVersionOutOfDateException.class.getName())) { |
| return new ClientVersionOutOfDateException(message); |
| } |
| if (className.equals(ServerKeyStoreException.class.getName())) { |
| return new ServerKeyStoreException(message); |
| } |
| if (className.equals(SessionTimedOutException.class.getName())) { |
| return new SessionTimedOutException(message); |
| } |
| if (className.equals(ConnectionException.class.getName())) { |
| return new ConnectionException(message); |
| } |
| if (className.equals(ESUpdateRequiredException.class.getName())) { |
| return new ESUpdateRequiredException(); |
| } |
| if (className.equals(FileTransferException.class.getName())) { |
| return new FileTransferException(message); |
| } |
| if (className.equals(FileNotOnServerException.class.getName())) { |
| return new FileNotOnServerException(message); |
| } |
| if (className.equals(InvalidInputException.class.getName())) { |
| return new InvalidInputException(message); |
| } |
| if (className.equals(InvalidProjectIdException.class.getName())) { |
| return new InvalidProjectIdException(message); |
| } |
| if (className.equals(InvalidVersionSpecException.class.getName())) { |
| return new InvalidVersionSpecException(message); |
| } |
| if (className.equals(SerializationException.class.getName())) { |
| return new SerializationException(message); |
| } |
| if (className.equals(StorageException.class.getName())) { |
| return new StorageException(message); |
| } |
| if (className.equals(UnknownSessionException.class.getName())) { |
| return new UnknownSessionException(message); |
| } |
| |
| // default behavior if previous matches didn't apply |
| return new ESException(message); |
| |
| } |
| |
| } |