/*
* Copyright 2009 NCHOVY
*
* Licensed 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.krakenapps.bundle;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.krakenapps.api.BundleManager;
import org.krakenapps.api.BundleRepository;
import org.krakenapps.api.BundleStatus;
import org.krakenapps.api.KeyStoreManager;
import org.krakenapps.api.MavenResolveException;
import org.krakenapps.api.Script;
import org.krakenapps.api.ScriptArgument;
import org.krakenapps.api.ScriptContext;
import org.krakenapps.api.ScriptUsage;
import org.krakenapps.main.Kraken;
import org.krakenapps.pkg.HttpWagon;
import org.krakenapps.pkg.MavenMetadata;
import org.krakenapps.pkg.ProgressMonitorImpl;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
public class BundleScript implements Script {
private BundleContext bc;
private ScriptContext context;
private BundleManager manager;
public BundleScript(BundleContext bc, BundleManager manager) {
this.bc = bc;
this.manager = manager;
}
@Override
public void setScriptContext(ScriptContext context) {
this.context = context;
}
public void refresh(String[] args) {
manager.refresh();
context.println("bundles are refreshed.");
}
private static class PriorityComparator implements Comparator<BundleRepository> {
@Override
public int compare(BundleRepository o1, BundleRepository o2) {
return o2.getPriority() - o1.getPriority();
}
}
public void downloadroot(String[] args) {
String path = new File(System.getProperty("kraken.download.dir")).getAbsolutePath().replaceAll("\\\\", "/");
context.println(path);
}
public void repositories(String[] args) {
try {
List<BundleRepository> repositories = manager.getRepositories();
context.println("Maven Bundle Repository");
drawLine(70);
Collections.sort(repositories, new PriorityComparator());
for (BundleRepository repo : repositories) {
String name = repo.getName();
if (repo.isAuthRequired())
name += " (http-auth)";
if (repo.isHttps())
context.printf("[(%3d) %s] %s, trust=%s, key=%s\n", repo.getPriority(), name, repo.getUrl(),
repo.getTrustStoreAlias(), repo.getKeyStoreAlias());
else
context.printf("[(%3d) %s] %s\n", repo.getPriority(), name, repo.getUrl());
}
} catch (Exception e) {
context.println("error: " + e.getMessage());
}
}
@ScriptUsage(description = "Add maven repository", arguments = {
@ScriptArgument(name = "alias", type = "string", description = "alias of the maven repository"),
@ScriptArgument(name = "url", type = "string", description = "url of the maven repository"),
@ScriptArgument(name = "priority", type = "integer", description = "priority of the repository", optional = true) })
public void addRepository(String[] args) {
try {
String alias = args[0];
BundleRepository repo = new BundleRepository(alias, new URL(args[1]));
int priority = 0;
if (args.length > 2) {
priority = Integer.parseInt(args[2]);
}
repo.setPriority(priority);
manager.addRepository(repo);
context.println(args[1] + " added.");
} catch (Exception e) {
context.println("error: " + e.getMessage());
}
}
private void setRepositoryPriority(String alias, int priority) {
BundleRepository repo = manager.getRepository(alias);
if (repo == null) {
context.println("repository not found");
return;
}
repo.setPriority(priority);
manager.updateRepository(repo);
context.println("ok");
}
@ScriptUsage(description = "add secure bundle repository", arguments = {
@ScriptArgument(name = "alias", type = "string", description = "the alias of bundle repository"),
@ScriptArgument(name = "url", type = "string", description = "the url of bundle repository"),
@ScriptArgument(name = "trust store alias", type = "string", description = "the alias of truststore"),
@ScriptArgument(name = "key store alias", type = "string", description = "the alias of keystore. if provided, client authentication will be used", optional = true),
@ScriptArgument(name = "priority", type = "integer", description = "priority of the repository", optional = true) })
public void addSecureRepository(String[] args) {
try {
String alias = args[0];
URL url = new URL(args[1]);
BundleRepository repo = new BundleRepository(alias, url);
repo.setTrustStoreAlias(args[2]);
if (args.length >= 4)
repo.setKeyStoreAlias(args[3]);
if (args.length >= 5)
repo.setPriority(Integer.parseInt(args[4]));
manager.addRepository(repo);
context.printf("secure repository [%s] added\n", alias);
} catch (MalformedURLException e) {
context.println("invalid url format");
} catch (IllegalStateException e) {
context.println("database failure");
}
}
@ScriptUsage(description = "Remove maven repository", arguments = { @ScriptArgument(name = "alias", type = "string", description = "alias of the maven repository") })
public void removeRepository(String[] args) {
try {
String alias = args[0];
manager.removeRepository(alias);
context.println(alias + " removed.");
} catch (Exception e) {
context.println("error: " + e.getMessage());
}
}
@ScriptUsage(description = "Set credential for repository http authentication", arguments = {
@ScriptArgument(name = "alias", type = "string", description = "alias of the maven repository"),
@ScriptArgument(name = "account", type = "string", description = "account for http authentication"),
@ScriptArgument(name = "password", type = "string", description = "password for http authentication") })
public void setHttpAuth(String[] args) {
BundleRepository repo = manager.getRepository(args[0]);
if (repo == null) {
context.println("repository not found");
return;
}
repo.setAccount(args[1]);
repo.setPassword(args[2]);
repo.setAuthRequired(true);
manager.updateRepository(repo);
context.println("ok");
}
@ScriptUsage(description = "Reset credential for repository http authentication", arguments = { @ScriptArgument(name = "alias", type = "string", description = "alias of the maven repository") })
public void resetHttpAuth(String[] args) {
BundleRepository repo = manager.getRepository(args[0]);
if (repo == null) {
context.println("repository not found");
return;
}
repo.setAccount(null);
repo.setPassword(null);
repo.setAuthRequired(false);
manager.updateRepository(repo);
context.println("ok");
}
@ScriptUsage(description = "Set priority of repository. Larger number means higher priority", arguments = {
@ScriptArgument(name = "alias", type = "string", description = "alias of the maven repository"),
@ScriptArgument(name = "new priority", type = "integer", description = "new priority of the repository") })
public void setRepositoryPriority(String[] args) {
String alias = args[0];
int newPriority = Integer.parseInt(args[1]);
setRepositoryPriority(alias, newPriority);
}
public void install(String[] args) {
try {
if (args.length == 0)
throw new IllegalArgumentException();
long bundleId = -1;
if (args.length == 1) {
if (args[0].startsWith("file://")) {
bundleId = manager.installBundle(args[0]);
} else if (args[0].startsWith("file:\\\\")) {
String path = args[0].replace('\\', '/');
bundleId = manager.installBundle(path);
} else if (args[0].startsWith("http://")) {
URL url = new URL(args[0]);
String dir = System.getProperty("kraken.download.dir");
String[] pathTokens = url.getPath().split("/");
File f = new File(dir, pathTokens[pathTokens.length - 1]);
f.getParentFile().mkdirs();
context.println("trying download to " + f.getAbsolutePath());
if (f.createNewFile()) {
byte[] b = HttpWagon.download(url);
FileOutputStream os = new FileOutputStream(f);
try {
os.write(b);
} finally {
os.close();
}
bundleId = manager.installBundle("file:///" + f.getAbsolutePath());
} else {
context.println("cannot download file, file already exists");
return;
}
} else {
context.println("local path should starts with file:// or file:\\\\");
return;
}
} else {
if (args.length > 3) {
throw new IllegalArgumentException();
}
String groupId = args[0];
String artifactId = args[1];
String version = null;
if (args.length == 3)
version = args[2];
bundleId = manager.installBundle(new ProgressMonitorImpl(context), groupId, artifactId, version);
}
context.printf("bundle [%d] loaded\n", bundleId);
} catch (MavenResolveException e) {
context.println("Artifact not found");
} catch (IllegalStateException e) {
context.println(e.getMessage());
} catch (IllegalArgumentException e) {
context.println("Usage: bundle.install bundlePath ");
context.println(" bundle.install groupId artifactId version");
context.println(" bundlePath example: file:///C:\\bundle\\sample.jar or file:///root/kraken/sample.jar");
} catch (MalformedURLException e) {
context.println("Invalid bundle download URL");
} catch (IOException e) {
context.println(e.getMessage());
}
}
@ScriptUsage(description = "restart the bundle(s)")
public void restart(String[] args) {
stop(args);
start(args);
}
@ScriptUsage(description = "start the bundle(s)")
public void start(String[] args) {
long bundleId = -1;
try {
for (String arg : args) {
bundleId = Long.parseLong(arg);
manager.startBundle(bundleId);
context.println("bundle " + bundleId + " started.");
}
} catch (Exception e) {
context.println(e.getMessage());
}
}
@ScriptUsage(description = "stop the bundle(s)")
public void stop(String[] args) {
long bundleId = -1;
try {
for (String arg : args) {
bundleId = Long.parseLong(arg);
manager.stopBundle(bundleId);
context.println("bundle " + bundleId + " stopped.");
}
} catch (Exception e) {
context.println("failed to stop bundle " + bundleId);
context.println(e.getMessage());
}
}
@ScriptUsage(description = "update the bundle(s)")
public void update(String[] args) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ");
try {
for (String arg : args) {
long bundleId = Long.parseLong(arg);
try {
Bundle b = bc.getBundle(bundleId);
if (b == null)
continue;
String before = (String) b.getHeaders().get("Bnd-LastModified");
manager.updateBundle(bundleId);
String after = (String) b.getHeaders().get("Bnd-LastModified");
context.print("bundle " + bundleId + " updated");
if (before != null && after != null) {
String beforeDate = dateFormat.format(new Date(Long.parseLong(before)));
String afterDate = dateFormat.format(new Date(Long.parseLong(after)));
if (beforeDate.equals(afterDate))
context.print(" (same build timestamp)");
else
context.print(", old timestamp: " + beforeDate + ", new timestamp: " + afterDate);
}
context.println();
} catch (RuntimeException re) {
context.println("failed to update bundle " + bundleId);
context.println("reason: " + re.getMessage());
}
}
} catch (Exception e) {
context.println(e.getMessage());
}
}
@ScriptUsage(description = "update all locally-installed bundle(s). before use this method, stop ipojo bundle first.", arguments = { @ScriptArgument(name = "isForced", description = "use 'force' to run this method.", optional = false, type = "force or not") })
public void updateAll(String[] args) {
if (args.length < 1 || !args[0].equals("force")) {
context.printf("Ignored. Use 'force' as argument.\n");
return;
}
try {
Map<Long, BundleStatus> bundles = manager.getBundles();
for (Long bundleId : bundles.keySet()) {
BundleStatus bundleStatus = bundles.get(bundleId);
try {
if (manager.isLocallyInstalledBundle(bundleId)) {
manager.updateBundle(bundleId);
context.printf("bundle [%d] %s %s updated.\n", bundleId, bundleStatus.getSymbolicName(),
bundleStatus.getVersion());
}
} catch (Exception be) {
continue;
}
}
} catch (Exception e) {
context.println(e.getMessage());
}
}
@ScriptUsage(description = "uninstall the bundle(s)")
public void uninstall(String[] args) {
for (String arg : args) {
long bundleId = Long.parseLong(arg);
if (manager.uninstallBundle(bundleId))
context.println("bundle " + bundleId + " uninstalled successfully.");
else
context.println("bundle " + bundleId + " uninstall failed.");
}
}
@ScriptUsage(description = "list all bundles", arguments = { @ScriptArgument(name = "filter", type = "string", description = "filter text for bundle symbolic name", optional = true) })
public void list(String[] args) {
String filterText = null;
if (args.length > 0)
filterText = args[0];
Map<Long, BundleStatus> bundles = manager.getBundles();
context.println("[ ID] Symbolic Name\t\t\t\tVersion\t Status");
drawLine(66);
Set<Long> sortedKeys = new TreeSet<Long>(bundles.keySet());
for (Long bundleId : sortedKeys) {
BundleStatus status = bundles.get(bundleId);
if (filterText != null) {
boolean filtered = false;
for (String arg : args) {
if (status.getSymbolicName().indexOf(arg) < 0)
filtered = true;
}
if (filtered)
continue;
}
context.printf("[%3d] %-41s %s\t %s\n", bundleId, status.getSymbolicName(), status.getVersion(),
status.getStateName());
}
}
@ScriptUsage(description = "print bundle location", arguments = { @ScriptArgument(name = "bundle id", description = "the bundle id") })
public void location(String[] args) {
try {
long bundleId = Long.parseLong(args[0]);
String location = manager.getBundleLocation(bundleId);
context.println(location);
} catch (IllegalStateException e) {
context.println("bundle not found");
}
}
@ScriptUsage(description = "list bundle resources", arguments = {
@ScriptArgument(name = "bundle id", description = "the bundle id"),
@ScriptArgument(name = "directory", description = "directory path", optional = true) })
public void resources(String[] args) {
long bundleId = Long.parseLong(args[0]);
String directory = "/";
if (args.length == 2) {
directory = args[1];
}
context.println("Bundle Resources");
context.println("-------------------");
try {
List<String> paths = manager.getEntryPaths(bundleId, directory);
for (String path : paths)
context.println(path.toString());
} catch (IllegalStateException e) {
context.println("bundle not found.");
}
}
@ScriptUsage(description = "view resource's content (only utf-8 encoding supported now)", arguments = {
@ScriptArgument(name = "bundle id", description = "the bundle id"),
@ScriptArgument(name = "path", description = "the resource path") })
public void resource(String[] args) {
long bundleId = Long.parseLong(args[0]);
String path = args[1];
try {
context.println(manager.getEntry(bundleId, path).replaceAll("%", "%%%%").replaceAll("\n", "\r\n"));
} catch (IllegalStateException e) {
context.println("bundle not found");
} catch (FileNotFoundException e) {
context.println("file not found");
} catch (IOException e) {
context.println("error occurred while file reading.");
}
}
private void drawLine(int length) {
for (int i = 0; i < length; ++i) {
context.print("-");
}
context.println("");
}
public void manifest(String[] args) {
int bundleId = Integer.parseInt(args[0]);
BundleContext bundleContext = Kraken.getContext();
Bundle bundle = bundleContext.getBundle(bundleId);
Enumeration<?> enumeration = bundle.getHeaders().keys();
while (enumeration.hasMoreElements()) {
Object key = enumeration.nextElement();
Object value = bundle.getHeaders().get(key);
context.printf("%s: %s\n", key, value);
}
Object lastModified = bundle.getHeaders().get("Bnd-LastModified");
if (lastModified != null) {
context.printf("%s\n", new Date(Long.parseLong((String) lastModified)));
}
}
public void timestamp(String[] args) {
int bundleId = -1;
String filterText = null;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ");
if (args.length != 0) {
try {
bundleId = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
filterText = args[0];
}
}
if (bundleId != -1) {
Bundle bundle = bc.getBundle(bundleId);
if (bundle == null) {
context.println("bundle [" + bundleId + "] not found");
return;
}
Object object = bundle.getHeaders().get("Bnd-LastModified");
if (object == null) {
context.printf("Bnd-LastModified not found in bundle manifest.\n");
return;
}
Date lastModified = new Date(Long.parseLong((String) object));
context.println(dateFormat.format(lastModified));
} else {
Map<Long, BundleStatus> bundles = manager.getBundles();
context.println("[ ID] Symbolic Name\t\t\t\tVersion\t Build Timestamp");
drawLine(80);
Set<Long> sortedKeys = new TreeSet<Long>(bundles.keySet());
for (Long key : sortedKeys) {
BundleStatus status = bundles.get(key);
if (filterText != null) {
boolean filtered = false;
for (String arg : args) {
if (status.getSymbolicName().indexOf(arg) < 0)
filtered = true;
}
if (filtered)
continue;
}
Date buildTimestamp = status.getBuildTimestamp();
context.printf("[%3d] %-41s %s\t %s\n", key, status.getSymbolicName(), status.getVersion(),
buildTimestamp == null ? "N/A" : dateFormat.format(buildTimestamp));
}
}
}
@ScriptUsage(description = "print installable bundle versions", arguments = {
@ScriptArgument(name = "group id", description = "bundle group id"),
@ScriptArgument(name = "artifact id", description = "bundle artifact id") })
public void versions(String[] args) {
BundleContext bc = Kraken.getContext();
ServiceReference ref = bc.getServiceReference(KeyStoreManager.class.getName());
KeyStoreManager keyman = (KeyStoreManager) bc.getService(ref);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss 'UTC'");
for (BundleRepository repo : manager.getRepositories()) {
try {
MavenMetadata mm = new MavenMetadata(repo, keyman, args[0], args[1]);
if (mm.getRelease() != null || mm.getLatest() != null || mm.getVersions() != null) {
context.println("Repository [" + repo + "]");
if (mm.getRelease() != null)
context.println("\trelease: " + mm.getRelease());
if (mm.getLatest() != null)
context.println("\tlatest: " + mm.getLatest());
if (mm.getVersions() != null)
context.println("\tversions: " + mm.getVersions());
if (mm.getLastUpdated() != null)
context.println("\tlast updated: " + dateFormat.format(mm.getLastUpdated()));
}
} catch (Exception e) {
}
}
}
}