/*******************************************************************************
* Copyright © 2012, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*
*******************************************************************************/
package org.eclipse.edt.ide.deployment.services.generators;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.edt.ide.core.utils.EclipseUtilities;
import org.eclipse.edt.ide.deployment.core.model.Restservice;
import org.eclipse.edt.ide.deployment.rui.internal.util.WebUtilities;
import org.eclipse.edt.ide.deployment.solution.DeploymentContext;
import org.eclipse.edt.javart.util.JavaAliaser;
import org.eclipse.edt.mof.egl.ExternalType;
import org.eclipse.edt.mof.egl.LogicAndDataPart;
import org.eclipse.edt.mof.egl.Service;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class ServiceUriMappingGenerator
{
private DeploymentContext context;
private String uriMappingFileName;
private Document document;
private IProject project;
private Element root;
private String projectName;
private LogicAndDataPart logicPart;
// private String contextRoot;
private boolean isHostProgramService;
private Restservice restService;
private static String gatewayServiceName = "UIGatewayService";
/**
<servicemappings>
<contextroot>MyTestProject</contextroot>
<classpath>cp1;cp2;</classpath>
<servicemapping classname="rest.services.Employee">
<uri eglfunction="$func_xxxx" httpFunction="GET" encoding="XML">/Employee</uri>
</servicemapping>
</servicemappings>
*/
public ServiceUriMappingGenerator( DeploymentContext context )
{
this.context = context;
}
public boolean visit( Service service, Restservice restService )
{
isHostProgramService = false;
gen( service, restService );
return false;
}
public boolean visit( ExternalType externalType, Restservice restService )
{
isHostProgramService = true;
gen( externalType, restService );
return false;
}
private void gen( LogicAndDataPart part, Restservice restService )
{
logicPart = part;
project = context.getTargetProject();
projectName = project.getName();
uriMappingFileName = ServiceUtilities.getUriMappingFileName( projectName );
this.restService = restService;
genUriMapping();
}
private void genUriMapping()
{
try
{
getRoot();
}
catch( Exception e )
{
//throw new JavaGenException( new Exception(Messages.bind(Messages.J2EEDeploymentSolution_87, uriMappingFileName), e) );
}
//String fullyQualifiedName = Aliaser.packageNameAlias( logicPart.getPackageName(), '.' ) + '.' + Utilities.getServiceCoreName( logicPart );
String fullyQualifiedName = JavaAliaser.packageNameAlias( logicPart.getCaseSensitivePackageName() ) + '.' + logicPart.getCaseSensitiveName();
removeServiceContextNode( RestServiceUtilities.CONTEXT_ROOT_ELEM );
removeServiceContextNode( RestServiceUtilities.CLASSPATH_ELEM );
removeServiceNode( fullyQualifiedName );
addServiceNode( fullyQualifiedName );
addContextNode();
try
{
addClasspathNode();
writeDocument();
}
catch( Exception e )
{
//throw new JavaGenException( new Exception(Messages.bind(Messages.J2EEDeploymentSolution_88, uriMappingFileName), e) );
}
}
private void removeServiceNode( String fullyQualifiedName )
{
NodeList mappings = root.getElementsByTagName( RestServiceUtilities.SERVICE_MAPPING_ELEM );
Element node = null;
ArrayList nodes2Remove = new ArrayList();
String className;
for( int idx = 0; idx < mappings.getLength(); idx++ )
{
node = (Element)mappings.item( idx );
className = node.getAttribute( RestServiceUtilities.CLASSNAME_ATTR );
if( className == null )
{
nodes2Remove.add( node );
}
else if( className.equals( fullyQualifiedName ) )
{
nodes2Remove.add( node );
}
}
for( int idx = 0; idx < nodes2Remove.size(); idx++ )
{
root.removeChild( (Node)nodes2Remove.get( idx ) );
}
}
private void removeServiceContextNode( String nodeName )
{
NodeList nodeList = root.getElementsByTagName( nodeName );
ArrayList nodes2Remove = new ArrayList();
for( int idx = 0; idx < nodeList.getLength(); idx++ )
{
nodes2Remove.add( (Element)nodeList.item( idx ) );
}
for( int idx = 0; idx < nodes2Remove.size(); idx++ )
{
root.removeChild( (Node)nodes2Remove.get( idx ) );
}
}
private void addContextNode()
{
Element serviceContextNode = document.createElement( RestServiceUtilities.CONTEXT_ROOT_ELEM );
root.appendChild( serviceContextNode );
serviceContextNode.appendChild( document.createTextNode( '/' + WebUtilities.getContextRoot(project) + '/' + ServiceUtilities.getRestServiceRoot() ) );
}
private void addClasspathNode() throws CoreException
{
// if( !context.getBuildDescriptor().getJ2EE() )
// {
// Element serviceContextNode = document.createElement( RestServiceUtilities.CLASSPATH_ELEM );
// root.appendChild( serviceContextNode );
// serviceContextNode.appendChild( document.createTextNode( getClasspath( project.getName() ) ) );
// }
}
private void addServiceNode( String fullyQualifiedName )
{
/*
<servicemapping classname="rest.services.Employee">
<uri eglfunction="$func_xxxx" httpFunction="GET" encoding"XML">/Employee</uri>
</servicemapping>
*/
Element serviceMappingNode = document.createElement( RestServiceUtilities.SERVICE_MAPPING_ELEM );
root.appendChild( serviceMappingNode );
serviceMappingNode.setAttribute( RestServiceUtilities.CLASSNAME_ATTR, fullyQualifiedName );
if( ServiceUtilities.isStateful( logicPart ) )
{
serviceMappingNode.setAttribute( RestServiceUtilities.STATEFUL_SERVICE_ATTR, RestServiceUtilities.TRUE_VALUE );
}
if( isHostProgramService )
{
serviceMappingNode.setAttribute( RestServiceUtilities.HOST_PROGRAM_SERVICE_ATTR, RestServiceUtilities.TRUE_VALUE );
}
Element uriNode = document.createElement( RestServiceUtilities.URI_ELEM );
uriNode.setAttribute(RestServiceUtilities.HTTP_FUNCTION_ATTR, RestServiceUtilities.HTTP_POST_METHOD);
// uriNode.setAttribute(RestServiceUtilities.IN_ENCODING_ATTR, org.eclipse.edt.javart.services.servlet.rest.rpc.RestServiceProjectInfo.ENCODING_STR_JSON);
// uriNode.setAttribute(RestServiceUtilities.OUT_ENCODING_ATTR, RestServiceProjectInfo.ENCODING_STR_JSON);
String nodeValue = ServiceUtilities.getUri( logicPart, restService );
uriNode.appendChild( document.createTextNode( nodeValue ) );
serviceMappingNode.appendChild( uriNode );
}
private void getRoot() throws Exception
{
String fullyQualifiedUriMappingFileName = project.getLocation().toPortableString();
List<IResource> folders = new ArrayList<IResource>();
org.eclipse.edt.ide.ui.internal.deployment.ui.DeploymentUtilities.getJavaSourceFolders(project, folders);
if ( folders.size() == 0 ) {
return;
}
String sourceFolder = folders.get(0).getFullPath().removeFirstSegments( 1 ).toOSString();
fullyQualifiedUriMappingFileName += '/' + sourceFolder + '/' + uriMappingFileName;
File file = new File( fullyQualifiedUriMappingFileName );
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
if( file.exists() )
{
try
{
document = builder.parse( file );
}
catch( Exception e ){}
}
if( document == null )
{
document = builder.newDocument();
}
NodeList roots = document.getElementsByTagName( RestServiceUtilities.SERVICES_MAPPINGS_ELEM );
if( roots == null || roots.getLength() == 0 )
{
root = document.createElement( RestServiceUtilities.SERVICES_MAPPINGS_ELEM );
document.appendChild( root );
}
else
{
root = (Element)roots.item( 0 );
}
}
private void writeDocument() throws Exception
{
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
cleanupDocument();
DOMSource source = new DOMSource(document);
ByteArrayOutputStream os = new ByteArrayOutputStream();
StreamResult result = new StreamResult( os );
transformer.transform(source, result);
InputStream bis = new ByteArrayInputStream( os.toByteArray() );
// ServiceFileWriter updater =
// new ServiceFileWriter( bis, uriMappingFileName, "", context.getBuildDescriptor(), null );
//
// //Run the updater. If something goes wrong, an exception will be thrown.
// EclipseUtilities.runUpdater( updater );
String javaSourceFolder = EclipseUtilities.getJavaSourceFolderName( context.getTargetProject() );
IPath targetFilePath = new Path( "/" + context.getTargetProject().getName() + "/" + javaSourceFolder + "/" + uriMappingFileName );
IFile targetFile = ResourcesPlugin.getWorkspace().getRoot().getFile(targetFilePath);
if( targetFile.exists() ) {
targetFile.setContents(bis, true, true, context.getMonitor());
} else {
targetFile.create(bis, true, context.getMonitor());
// targetFile.setLocalTimeStamp(file.getLocalTimeStamp());
}
os.close();
bis.close();
}
private void cleanupDocument()
{
document.normalize();
NodeList nodes = root.getChildNodes();
Node node;
for( int idx = 0; idx < nodes.getLength(); idx++ )
{
node = nodes.item( idx );
if( node.getNodeType() != Node.ELEMENT_NODE )
{
root.removeChild(node);
}
}
}
private String getClasspath( String projectName ) throws CoreException
{
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
IJavaProject javaProject = (IJavaProject)project.getNature( JavaCore.NATURE_ID );
String classpath = "";
try
{
if( javaProject != null )
{
classpath = createClasspath(javaProject);
}
}
catch (IOException e1)
{
// throw new JavaGenException( new Exception( Messages.bind(Messages.J2EEDeploymentSolution_86, projectName), e1 ));
}
catch( URISyntaxException use )
{
// throw new JavaGenException( new Exception( Messages.bind(Messages.J2EEDeploymentSolution_86, projectName), use ));
}
return classpath;
}
private static String createClasspath(IJavaProject javaProject ) throws JavaModelException, MalformedURLException, URISyntaxException
{
StringBuffer classpath = new StringBuffer();
String path;
IClasspathEntry[] resolvedClasspath = javaProject.getResolvedClasspath(true);
for (int i = 0; i < resolvedClasspath.length; i++) {
IClasspathEntry entry = resolvedClasspath[i];
if(entry.getEntryKind() != IClasspathEntry.CPE_SOURCE)
{
path = entry.getPath().toPortableString();
}
else
{
if(entry.getOutputLocation() != null)
{
path = javaProject.getProject().getLocation().removeLastSegments(1).append(entry.getOutputLocation()).toPortableString();
}
else
{
path = javaProject.getProject().getLocation().removeLastSegments(1).append(javaProject.getOutputLocation()).toPortableString();
}
}
classpath.append(path);
classpath.append( ";" );
}
return classpath.toString();
}
// public static void mapUIGatewayService( Context context )
// {
// ElementFactoryImpl factory = new ElementFactoryImpl();
// Service service= factory.createService( factory.createName(gatewayServiceName));
// service.setPackageName(gatewayServicePackage);
// CommonUtilities.addAnnotation(service, context, Constants.SERVICE_STATEFUL_ANNOTATION, new Boolean( true ) );
// CommonUtilities.addAnnotation(service, context, Constants.SERVICE_URI_ANNOTATION, "/" + gatewayServiceName);
// service.accept( new ServiceUriMappingGenerator( context ) );
// CommonUtilities.removeAnnotation(service, Constants.SERVICE_STATEFUL_ANNOTATION);
// CommonUtilities.removeAnnotation(service, Constants.SERVICE_URI_ANNOTATION);
// }
}