Package org.apache.geronimo.st.core.operations

Source Code of org.apache.geronimo.st.core.operations.SharedLibEntryCreationOperation

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.geronimo.st.core.operations;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;

import javax.enterprise.deploy.spi.DeploymentManager;
import javax.enterprise.deploy.spi.TargetModuleID;
import javax.enterprise.deploy.spi.status.DeploymentStatus;
import javax.enterprise.deploy.spi.status.ProgressObject;
import javax.management.MBeanServerConnection;
import javax.management.ObjectInstance;
import javax.management.ObjectName;

import org.apache.geronimo.st.core.Activator;
import org.apache.geronimo.st.core.GeronimoServerBehaviourDelegate;
import org.apache.geronimo.st.core.GeronimoUtils;
import org.apache.geronimo.st.core.commands.DeploymentCommandFactory;
import org.apache.geronimo.st.core.internal.Trace;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IClasspathContainer;
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.eclipse.jst.j2ee.internal.deployables.J2EEFlexProjDeployable;
import org.eclipse.wst.common.frameworks.datamodel.AbstractDataModelOperation;
import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
import org.eclipse.wst.server.core.IModule;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.ServerUtil;
import org.eclipse.wst.server.core.internal.ProgressUtil;
import org.eclipse.wst.server.core.model.ModuleDelegate;

/**
* @version $Rev: 817996 $ $Date: 2009-09-23 16:04:12 +0800 (Wed, 23 Sep 2009) $
*/
public class SharedLibEntryCreationOperation extends AbstractDataModelOperation implements ISharedLibEntryCreationDataModelProperties {
 
  private TargetModuleID sharedLibTarget;
  private IServer server;
  private IProgressMonitor monitor;
  private IPath sharedLibLocation;
  private static final IPath TEMP_LOCATION = Activator.getDefault().getStateLocation().append("shared-lib-temp");

  public SharedLibEntryCreationOperation() {
  }

  /**
   * @param model
   */
  public SharedLibEntryCreationOperation(IDataModel model) {
    super(model);
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.core.commands.operations.AbstractOperation#execute(org.eclipse.core.runtime.IProgressMonitor,
   *      org.eclipse.core.runtime.IAdaptable)
   */
  public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
    Trace.trace(Trace.INFO, ">> SharedLibEntryCreationOperation.execute()");
   
    this.monitor = ProgressUtil.getMonitorFor(monitor);
    this.monitor.beginTask("Processing in-place shared libraries.", 100);
   
    IModule[] modules = (IModule[]) model.getProperty(MODULES);
    this.server = (IServer) model.getProperty(SERVER);
   
    HashMap<File, File> addList = new HashMap<File, File>();
    List<File> deleteList = new ArrayList<File>();
   
    try {
      String sharedLibPath = getSharedLibPath();
      if(sharedLibPath == null)
        return Status.CANCEL_STATUS;
     
      sharedLibLocation = server.getRuntime().getLocation().append(sharedLibPath);
     
      for(int i = 0; i < modules.length; i++) {
        IModule module = modules[i];
        IProject project = module.getProject();
       
        File dummyJarFile = sharedLibLocation.append(project.getName() + ".eclipse.jar").toFile();
        // delete the dummy jar if module no longer associated with server
        if (!ServerUtil.containsModule(server, module, monitor) && dummyJarFile.exists()) {
          deleteList.add(dummyJarFile);
        } else {
          HashSet entries = new HashSet();
          J2EEFlexProjDeployable j2eeModule = (J2EEFlexProjDeployable) module.loadAdapter(J2EEFlexProjDeployable.class, null);
          if(GeronimoUtils.isEarModule(module)) {
            IModule[] childModules = j2eeModule.getChildModules();
            for(int j = 0; j < modules.length; j++) {
              entries.addAll(processModule(childModules[i]));
            }
          } else {
            entries.addAll(processModule(module));
          }

          // regen the jar only if required
          if (regenerate(dummyJarFile, entries)) {
            TEMP_LOCATION.toFile().mkdirs();
            File temp = TEMP_LOCATION.append(project.getName() + ".eclipse.jar").toFile();
            Trace.trace(Trace.INFO, "Updating external sharedlib entries for " + module.getName());
            if(temp.exists())
              delete(temp);
            Manifest manifest = new Manifest();
            Attributes attributes = manifest.getMainAttributes();
            attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
            attributes.put(Attributes.Name.CLASS_PATH, getCPEntriesAsString(entries));
            JarOutputStream os = new JarOutputStream(new FileOutputStream(temp), manifest);
            os.flush();
            os.close();
            addList.put(temp, dummyJarFile);
          }
        }
      }
     
      updateAndRecycleSharedLib(addList, deleteList);
     
    }catch (CoreException e){
      IStatus status = e.getStatus();
      Trace.trace(Trace.SEVERE, status.getMessage(), e);
      throw new ExecutionException(status.getMessage(), e);
    }catch (Exception e) {
      Trace.trace(Trace.SEVERE, "Failure in updating shared library.", e);
      throw new ExecutionException("Failure in updating shared library", e);
    } finally {
      monitor.done();
    }
   
    Trace.trace(Trace.INFO, "<< SharedLibEntryCreationOperation.execute()");
    return Status.OK_STATUS;
  }
 
  private void updateAndRecycleSharedLib(HashMap addList, List deleteList) throws Exception {
    if(addList.size() > 0 || deleteList.size() > 0) {
      stopSharedLib();
      for(int i = 0; i < deleteList.size(); i++) {
        File file = (File) deleteList.get(i);
        delete(file);
      }
      Iterator i = addList.keySet().iterator();
      while(i.hasNext()) {
        File src = (File) i.next();
        File dest = (File) addList.get(src);
        if(dest.exists()) {
          delete(dest);
        }
        copy(src, dest);
      }
      startSharedLib();
    }
  }
 
  private void copy(File src, File dest) throws Exception {
    try {
      InputStream in = new FileInputStream(src);
      OutputStream out = new FileOutputStream(dest);
      byte[] buf = new byte[1024];
      int len;
      while ((len = in.read(buf)) > 0) {
        out.write(buf, 0, len);
      }
      in.close();
      out.close();
    } catch (Exception e) {
      throw e;
    }
    Trace.trace(Trace.INFO, "Created " + dest.getAbsolutePath());
  }

  private String getSharedLibPath() throws Exception {
    // locate the path of the first sharedlib library folder
    GeronimoServerBehaviourDelegate gsDelegate = (GeronimoServerBehaviourDelegate) server.getAdapter(GeronimoServerBehaviourDelegate.class);
    MBeanServerConnection connection = gsDelegate.getServerConnection();
    Set result = connection.queryMBeans(new ObjectName("*:j2eeType=GBean,name=SharedLib,*"), null);
    if (!result.isEmpty()) {
      ObjectInstance instance = (ObjectInstance) result.toArray()[0];
      String[] libDirs = (String[]) connection.getAttribute(instance.getObjectName(),"libDirs");
      if (libDirs != null && libDirs.length > 0) {
        return libDirs[0];
      }
    }
    return null;
  }
 
  private HashSet processModule(IModule module) throws Exception {
    Trace.trace(Trace.INFO, "SharedLibEntryCreationOperation.process() " + module.getName());

    IProject project = module.getProject();
    // filter the cp entries needed to be added to the dummy shared lib
    // jar
    HashSet entries = new HashSet();
    processJavaProject(project, entries, false);

    // add output locations of referenced projects excluding non-child
    // projects
    ModuleDelegate delegate = (ModuleDelegate) module.loadAdapter(ModuleDelegate.class, null);
    if(delegate != null) {
      IProject[] refs = project.getReferencedProjects();
      for(int i = 0; i < refs.length; i++) {
        boolean found = false;
        IModule[] children = delegate.getChildModules();
        for(int j = 0; j < children.length; j++) {
          if(children[j].getProject().equals(refs[i])) {
            found = true;
            break;
          }
        }
        if(!found) {
          processJavaProject(refs[i], entries, true);
        }
      }
    }
    return entries;
  }

  private void delete(File dummyJarFile) throws CoreException {
    if(dummyJarFile.delete()) {
      Trace.trace(Trace.INFO, dummyJarFile.getAbsolutePath() + " deleted sucessfully.");
    } else {
      Trace.trace(Trace.SEVERE, "Failed to delete " + dummyJarFile.getAbsolutePath(), null);
      throw new CoreException(new Status(IStatus.ERROR,Activator.PLUGIN_ID,"Failed to delete " + dummyJarFile.getAbsolutePath(),null));
    }
  }

  private void processJavaProject(IProject project, HashSet entries, boolean includeOutputLocations) throws JavaModelException {
    IJavaProject jp = JavaCore.create(project);
    IClasspathEntry[] cp = jp.getRawClasspath();
    for (int i = 0; i < cp.length; i++) {
      IClasspathEntry entry = cp[i];
      int kind = entry.getEntryKind();
      String path = null;
      if(kind == IClasspathEntry.CPE_CONTAINER) {
        if("org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER".equals(entry.getPath().toString())) {
          IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), jp);
          IClasspathEntry[] containerEntries = container.getClasspathEntries();
          for(int j = 0; j  < containerEntries.length; j++) {
            addEntry(entries, resolveVarOrLibEntry(containerEntries[j]));
          }
        }
      } else if (kind == IClasspathEntry.CPE_PROJECT) {
        IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject(entry.getPath().segment(0));
        IJavaProject ref = JavaCore.create(p);
        path = p.getLocation().removeLastSegments(1).append(ref.getOutputLocation()).addTrailingSeparator().toOSString();
      } else if (kind == IClasspathEntry.CPE_SOURCE) {
        // this if not combined with parent statement to filter out
        // CPE_SOURCE entries from following else statement
        // if no outputlocation, output path will get picked up by
        // default output path
        if(includeOutputLocations && entry.getOutputLocation() != null) {
                    path = project.getLocation().append(entry.getOutputLocation().removeFirstSegments(1)).addTrailingSeparator().toOSString();
        }
      } else {
        path = resolveVarOrLibEntry(entry);
      }
      addEntry(entries, path);
    }
   
    if(includeOutputLocations) {
            String path = project.getLocation().append(jp.getOutputLocation().removeFirstSegments(1)).addTrailingSeparator().toOSString();
      addEntry(entries, path);
    }
  }

  private String resolveVarOrLibEntry(IClasspathEntry entry) {
    IClasspathEntry resolved = JavaCore.getResolvedClasspathEntry(entry);
    IPath resolvedPath = resolved.getPath().makeAbsolute();
    IProject candiate = ResourcesPlugin.getWorkspace().getRoot().getProject(resolvedPath.segment(0));
    // check if resolvedPath is a project resource
    if(candiate.exists(resolvedPath.removeFirstSegments(1))) {
      return candiate.getLocation().append(resolvedPath.removeFirstSegments(1)).toOSString();
    } else {
      return resolvedPath.toOSString();
    }
  }

  private void addEntry(HashSet entries, String path) {
    if(path != null) {
      File f = new File(path);
      try {
        String url = f.toURL().toExternalForm();
        if (!entries.contains(url)) {
          Trace.trace(Trace.INFO, "Adding " + url);
          monitor.subTask("Linking " + url + " to shared lib.");
          entries.add(url);
        }
      } catch (MalformedURLException e1) {
        Trace.trace(Trace.INFO, "Failed to add " + path);
        e1.printStackTrace();
      }
    }
  }

  /**
   * @param entries
   * @return
   */
  private String getCPEntriesAsString(Set entries) {
    StringBuffer buffer = new StringBuffer();
    Iterator i = entries.iterator();
    while (i.hasNext()) {
      String cpEntry = (String) i.next();
      buffer.append(cpEntry);
      if (i.hasNext()) {
        buffer.append(" ");
      }
    }
    return buffer.toString();
  }

  /**
   * @param jarPath
   * @param entries
   * @return
   * @throws Exception
   */
  private boolean regenerate(File jarFile, Set entries) throws Exception {
    if (jarFile.exists()) {
      if (entries.isEmpty()) {
        // go ahead and return if zero entires, dummy jar will be
        // deleted
        return true;
      } else {
        JarFile jar = new JarFile(jarFile);
        Manifest manifest = jar.getManifest();
        Attributes attributes = manifest.getMainAttributes();
        String value = attributes.getValue(Attributes.Name.CLASS_PATH);
        jar.close();

        Set currentEntries = new HashSet();
        if (value != null) {
          StringTokenizer tokenizer = new StringTokenizer(value);
          while (tokenizer.hasMoreTokens()) {
            currentEntries.add(tokenizer.nextToken());
          }
        }
        // regen dummy jar if old and new entries don't match
        return !entries.equals(currentEntries);
      }
    }

    return !entries.isEmpty();
  }
 
  private void stopSharedLib() throws Exception {
    DeploymentManager dm = DeploymentCommandFactory.getDeploymentManager(server);
    TargetModuleID id = getSharedLibTargetModuleID();
    TargetModuleID[] ids = new TargetModuleID[]{id};
    ProgressObject po = dm.stop(ids);
    waitForProgress(po);
    if(po.getDeploymentStatus().isFailed()) {
      throw new Exception(po.getDeploymentStatus().getMessage());
    }
  }
 
  private void startSharedLib() throws Exception {
    DeploymentManager dm = DeploymentCommandFactory.getDeploymentManager(server);
    TargetModuleID id = getSharedLibTargetModuleID();
    ProgressObject po = dm.start(new TargetModuleID[]{id});
    waitForProgress(po);
    if(po.getDeploymentStatus().isFailed()) {
      throw new Exception(po.getDeploymentStatus().getMessage());
    }
  }
 
  private TargetModuleID getSharedLibTargetModuleID() throws Exception {
    if(sharedLibTarget == null) {
      DeploymentManager dm = DeploymentCommandFactory.getDeploymentManager(server);
      TargetModuleID[] ids = dm.getAvailableModules(null, dm.getTargets());
      for(int i = 0; i < ids.length; i++) {
        if(ids[i].getModuleID().indexOf("sharedlib") > 0) {
          sharedLibTarget = ids[i];
          break;
        }
      } 
    }
   
    if(sharedLibTarget == null) {
      throw new Exception("Could not determine SharedLib TargetModuleID.");
    }
   
    return sharedLibTarget;
  }

  private void waitForProgress(ProgressObject po) {
    while (po.getDeploymentStatus().isRunning()) {
      try {
        Thread.sleep(100);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    DeploymentStatus status = po.getDeploymentStatus();
    String command = status.getCommand().toString();
    String state = status.getState().toString();
    Trace.trace(Trace.INFO, "SharedLib " + " " + command + " " + state);
  }
}
TOP

Related Classes of org.apache.geronimo.st.core.operations.SharedLibEntryCreationOperation

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.