Skip to content

Commit

Permalink
JBDS-2552 / JBDS 2553 : add offline support (via script)
Browse files Browse the repository at this point in the history
Signed-off-by: Fred Bricon <fbricon@gmail.com>
  • Loading branch information
fbricon committed Jun 12, 2013
1 parent 5364d5e commit 1c74dfd
Show file tree
Hide file tree
Showing 15 changed files with 782 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ bin.includes = META-INF/,\
about.mappings,\
about.properties,\
schema/,\
jboss_about.png
jboss_about.png,\
offline/
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
/*************************************************************************************
* Copyright (c) 2013 Red Hat, Inc. 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:
* JBoss by Red Hat - Initial implementation.
************************************************************************************/
@Grab(group='org.jboss.jdf', module='stacks-client', version='1.0.1.Final')
@Grab(group='commons-io', module='commons-io', version='2.4')
//jcommander is included in the groovy distro by accident, better make sure we express a direct dependency here
@Grab(group='com.beust', module='jcommander', version='1.30')

import org.apache.commons.io.FileUtils
import static groovyx.gpars.GParsPool.*
import static groovy.io.FileType.*
import com.beust.jcommander.*
import org.jboss.jdf.stacks.client.StacksClient
import org.jboss.jdf.stacks.model.*

class GoOfflineScript {
@Parameter(description = "<descriptor url list>")
def descriptors = ["http://download.jboss.org/jbosstools/examples/project-examples-maven-4.1.Alpha2.xml",
"http://download.jboss.org/jbosstools/examples/project-examples-community-4.1.Alpha2.xml"];

@Parameter(names =["-c", "--clean"], description = "Clean offline directory")
boolean clean = false

@Parameter(names =["-q", "--quiet"], description = "Quiet mode (reduced console output)")
boolean quiet = false

@Parameter(names =["-od", "--offline-dir"], description = "Base offline directory")
File offlineDir = new File("offline")

/*@Parameter(names =["-i", "--interactive"], description = "Interactive mode")
boolean interactive = false
@Parameter(names =["-fcd", "--final-cache-dir"], description = "Final cache directory used by JBoss Tools/JBDS")
File finalCacheDir = new File(System.getProperty("user.home"), ".jbosstools/cache")
@Parameter(names =["-lmr", "--local-maven-repo"], description = "Local Maven repository")
File localMavenRepoDir = new File(System.getProperty("user.home"), ".m2/repository")
*/
@Parameter(names = ["-h", "--help"], description = "This help", help = true)
boolean help;

public static main(args) {
def script = new GoOfflineScript()
def cmd = new JCommander();
try {
cmd.addObject(script);
cmd.parse(args)
} catch (ParameterException e) {
println e.getLocalizedMessage()
cmd.usage();
return
}

if (script.help) {
cmd.usage();
return
}
script.goOffline()
}

def goOffline (args) {
println "Descriptors : "+ descriptors
long start = System.currentTimeMillis()

if (clean && offlineDir.exists()) {
println "deleting existing $offlineDir"
if (!offlineDir.deleteDir()) {
throw new IOException("Could not delete $offlineDir")
}
}

def downloadDir = new File(offlineDir, ".jbosstools/cache")

println "creating $downloadDir"
downloadDir.mkdirs()

//This is the directory where examples will be unzipped to be built
def workDir = new File(offlineDir, "workDir")

descriptors.each { descriptorUrl ->
downloadExamples(descriptorUrl, downloadDir, workDir)
}

def mavenRepoDir = new File(offlineDir, ".m2/repository")

buildExamplesDir(workDir, mavenRepoDir)

buildArchetypesFromStacks(workDir, mavenRepoDir)

/*FIXME add interactive support
boolean copyCache = false
boolean copyMaven = false
if (copyCache && downloadDir.exists()) {
println "Copy $downloadDir to $finalCacheDir"
FileUtils.copyDirectory(downloadDir, finalCacheDir)
}
if (copyMaven && mavenRepoDir.exists()) {
FileUtils.copyDirectory(mavenRepoDir, localMavenRepoDir)
}
*/
long elapsed = System.currentTimeMillis() -start

println "Script executed in $elapsed ms"
}


////////////////////////////////////////////////////////////////////////////////////////////////////
def downloadExamples(descriptorUrl, downloadArea, workDir) {
if (!descriptorUrl) {
return
}
//download descriptor
println "parsing $descriptorUrl"
def descrUrl = new URL(descriptorUrl)
def localDescriptor = new File(downloadArea, descrUrl.getFile())
//Descriptors are cheap to download/update
FileUtils.copyURLToFile(descrUrl, localDescriptor)

def root = new XmlSlurper(false,false).parse(localDescriptor)

//foreach example in descriptor
def projects = root.project

if (projects.size() == 0) {
return
}

withPool(4) {
projects.eachParallel { p ->
String sUrl = p.url?.text().trim()
if (!sUrl) {
return
}
URL url = new URL(sUrl)
def zip = new File(downloadArea, url.getFile())
//println "Starting download of $url"
if (!zip.exists()) {
FileUtils.copyURLToFile(url, zip)
def totalSize = FileUtils.byteCountToDisplaySize(zip.size())

println "Downloaded $url ($totalSize) to $zip"
}
if ("maven" == p.importType.text()) {
def ant = new AntBuilder() // create an antbuilder
ant.unzip( src: zip, dest: new File(workDir, zip.getName()), overwrite:"false")
}
}
}
}

def buildExamplesDir(workDir, localRepo) {
workDir.eachFileMatch DIRECTORIES, ~/.*\.zip/, { unzipped ->
execMavenGoOffline(unzipped, localRepo)
}
}

def buildArchetypesFromStacks(workDir, localRepo) {
Stacks stacks = new StacksClient().getStacks();
stacks.getAvailableArchetypes().each { a ->
File folder = new File(workDir, a.artifactId)
if (folder.exists()) {
folder.deleteDir()
}
folder.mkdirs()
execMavenArchetypeBuild (a.groupId, a.artifactId, a.recommendedVersion, folder, localRepo)
execMavenGoOffline(new File(folder, "myapp"), localRepo)
}
}

def execMavenGoOffline (def directory, def localRepo) {
def ant = new AntBuilder()
def pom = new File(directory, "pom.xml")
if (!pom.exists()) {
if (!quiet) println "$pom can't be found. Skipping maven build"
return
}

def pomModel = new XmlSlurper(false,false).parse(pom)
def profiles = pomModel?.profiles?.profile?.id.collect{ it.text()}.join(",")
if (!quiet) println "Building ${pomModel.groupId}:${pomModel.artifactId}:${pomModel.version} " + profiles?:"with profiles $profiles"

//Spit everything to the current console
if (!quiet) {
ant.project.getBuildListeners().each{
it.setOutputPrintStream(System.out)
}
}
//remove [exec] prefixes
def logger = ant.project.buildListeners.find { it instanceof org.apache.tools.ant.DefaultLogger }
logger.emacsMode = true

ant.exec(errorproperty: "cmdErr",
resultproperty:"cmdExit",
failonerror: "false",
dir: directory,
executable: getMavenExec()) {
//arg(value:"--quiet")
arg(value:"dependency:go-offline")
if (profiles) arg(value:"-P$profiles")
if (localRepo) arg(value:"-Dmaven.repo.local=${localRepo.absolutePath}")
}
}

String getMavenExec() {
def mvnFileName="mvn"
if (System.properties['os.name'].toLowerCase().contains('windows')) {
mvnFileName+=".bat"
}
mvnFileName
}

def execMavenArchetypeBuild (groupId, artifactId, version, directory, localRepo) {
def ant = new AntBuilder()
//Spit everything to the current console
if (!quiet) {
ant.project.getBuildListeners().each{
it.setOutputPrintStream(System.out)
}
}
//remove [exec] prefixes
def logger = ant.project.buildListeners.find { it instanceof org.apache.tools.ant.DefaultLogger }
logger.emacsMode = true

ant.exec(errorproperty: "cmdErr",
resultproperty:"cmdExit",
failonerror: "false",
dir: directory,
executable: getMavenExec()) {
arg(value:"archetype:generate")
//arg(value:"--quiet")
arg(value:"-DarchetypeGroupId=${groupId}")
arg(value:"-DarchetypeArtifactId=${artifactId}")
arg(value:"-DarchetypeVersion=${version}")
arg(value:"-DgroupId=foo.bar")
arg(value:"-DartifactId=myapp")
arg(value:"-DinteractiveMode=false")
arg(value:"-Dversion=1.0.0-SNAPSHOT")
if (localRepo) arg(value:"-Dmaven.repo.local=${localRepo.absolutePath}")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ Project_Examples_wizard = Project Examples
Project_Examples_command =Project Examples...
ProjectExamples=Project Examples file
Project_Examples = Project Examples
Offline_Support = Offline Support
ProjectExampleCategories = Project Examples categories
5 changes: 5 additions & 0 deletions examples/plugins/org.jboss.tools.project.examples/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@
class="org.jboss.tools.project.examples.preferences.ProjectExamplesPreferencePage"
id="org.jboss.tools.project.examples.preferences.projectExamplesPreferencePage"
name="%Project_Examples"/>
<page
category="org.jboss.tools.project.examples.preferences.projectExamplesPreferencePage"
class="org.jboss.tools.project.examples.preferences.OfflineSupportPreferencePage"
id="org.jboss.tools.project.examples.preferences.offlineSupportPreferencePage"
name="%Offline_Support"/>
</extension>

<extension
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
Expand Down Expand Up @@ -167,6 +165,7 @@ public class ProjectExamplesActivator extends AbstractUIPlugin {
public static final String PROJECT_EXAMPLES_DEFAULT = "projectExamplesDefaultLocation"; //$NON-NLS-1$
public static final boolean PROJECT_EXAMPLES_DEFAULT_VALUE = true;


public static final String SHOW_PROJECT_READY_WIZARD = "showProjectRadyWizard"; //$NON-NLS-1$
public static final boolean SHOW_PROJECT_READY_WIZARD_VALUE = true;

Expand All @@ -175,6 +174,11 @@ public class ProjectExamplesActivator extends AbstractUIPlugin {

public static final String SHOW_QUICK_FIX = "showQuickFix"; //$NON-NLS-1$
public static final boolean SHOW_QUICK_FIX_VALUE = true;

public static final String PROJECT_EXAMPLES_OFFLINE_DIRECTORY = "projectExamplesOfflineDirectory"; //$NON-NLS-1$
public static final String PROJECT_EXAMPLES_OFFLINE_DIRECTORY_VALUE = new File( System.getProperty( "user.home" ), ".jbosstools/cache" ).getAbsolutePath(); //$NON-NLS-1$ //$NON-NLS-2$
public static final String PROJECT_EXAMPLES_OFFLINE_ENABLED = "projectExamplesOfflineEnabled";//$NON-NLS-1$
public static final boolean PROJECT_EXAMPLES_OFFLINE_ENABLED_VALUE = false;

private static final String IMPORT_PROJECT_EXAMPLES_EXTENSION_ID = "org.jboss.tools.project.examples.importProjectExamples"; //$NON-NLS-1$
private static final String TYPE = "type"; //$NON-NLS-1$
Expand Down Expand Up @@ -231,7 +235,7 @@ protected IStatus run(IProgressMonitor monitor) {
private ImportDefaultProjectExample defaultImportProjectExample;

private Map<String, List<ContributedPage>> contributedPages;

/**
* The constructor
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*************************************************************************************
* Copyright (c) 2013 Red Hat, Inc. 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:
* JBoss by Red Hat - Initial implementation.
************************************************************************************/
package org.jboss.tools.project.examples.internal.offline;

import java.io.File;
import java.net.URL;

import org.apache.commons.io.FileUtils;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.jboss.tools.project.examples.ProjectExamplesActivator;
import org.jboss.tools.project.examples.offline.OfflineUtil;


/**
* Extracts the embedded go_offline.groovy script to the workspace plugin state location.
*
* @author Fred Bricon
*
*/
public class ExtractScriptJob extends Job {

public static class ExtractScriptJobRule implements ISchedulingRule {

public boolean contains(ISchedulingRule rule) {
return rule == this;
}

public boolean isConflicting(ISchedulingRule rule) {
return rule == this;
}

}

public ExtractScriptJob() {
super("Extract go_offline script"); //$NON-NLS-1$
setRule(new ExtractScriptJobRule());
}

@Override
protected IStatus run(IProgressMonitor monitor) {
File offlineScript = OfflineUtil.getGoOfflineScript();
//No need to overwrite existing script if not in dev mode
if (!offlineScript.exists() || offlineScript.getName().contains(".qualifier")) { //$NON-NLS-1$
try {
URL scriptUrl = new URL("platform:/plugin/org.jboss.tools.project.examples/offline/go_offline.groovy"); //$NON-NLS-1$
URL sourceUrl = FileLocator.resolve(scriptUrl);
FileUtils.copyURLToFile(sourceUrl, offlineScript);
} catch (Exception e) {
Status error = new Status(IStatus.ERROR, ProjectExamplesActivator.PLUGIN_ID, "Impossible to copy the go_offline script", e); //$NON-NLS-1$
return error;
}
}
return Status.OK_STATUS;
}
}

0 comments on commit 1c74dfd

Please sign in to comment.