/*******************************************************************************
* Copyright (c) 2012 VMware, Inc.
* 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:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.osgi.runtime.builder;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.ui.progress.IProgressConstants;
import org.springframework.ide.eclipse.osgi.runtime.OsgiPlugin;
import org.springframework.ide.eclipse.osgi.runtime.OsgiUiImages;
import org.springframework.ide.eclipse.osgi.runtime.builder.OsgiBundleUpdateBuilder.Command;
/**
* Eclipse {@link Job} implementation that is scheduled to do an update or
* refresh of the given bundle identified by its symbolic name.
* @author Christian Dupuis
* @author Leo Dos Santos
* @since 1.0
*/
class OsgiUpdateJob extends Job {
private static final String YES_COMMAND = "y";
private static final String DISCONNECT_COMMAND = "disconnect";
public static final Object MODEL_CONTENT_FAMILY = new Object();
private String symbolicName;
private Command command;
/**
* Private Constructor.
* @param symbolicName the bundle identifier to update
* @param command the command to execute; either refresh or update
* @see #schedule(String, Command)
*/
private OsgiUpdateJob(String symbolicName, Command command) {
super("Refreshing bundle with symbolic name '" + symbolicName + "'");
this.symbolicName = symbolicName;
this.command = command;
}
/*
* (non-Javadoc)
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
protected IStatus run(IProgressMonitor monitor) {
// First make sure that only one Job at a time is scheduled that is
// responsible for updating the same bundle
synchronized (getClass()) {
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
Job[] buildJobs = Job.getJobManager().find(MODEL_CONTENT_FAMILY);
for (int i = 0; i < buildJobs.length; i++) {
Job curr = buildJobs[i];
if (curr != this && curr instanceof OsgiUpdateJob) {
OsgiUpdateJob job = (OsgiUpdateJob) curr;
if (job.isCoveredBy(this)) {
curr.cancel();
}
}
}
}
// Get the port from the preferences store
int port = getPort();
monitor.beginTask("Connecting to OSGi runtime running at port " + port,
1);
// Open socket to console and emit command
BufferedReader in = null;
PrintWriter out = null;
try {
Socket socket = new Socket(InetAddress.getLocalHost(), port);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
emitCommnad(out, command.toString().toLowerCase() + " " + symbolicName);
emitCommnad(out, DISCONNECT_COMMAND);
emitCommnad(out, YES_COMMAND);
}
catch (Exception e) {
// ignore all exceptions here
}
finally {
if (out != null) {
out.close();
}
if (in != null)
try {
{
in.close();
}
}
catch (IOException e) {
}
}
return Status.OK_STATUS;
}
private void emitCommnad(PrintWriter writer, String command) throws Exception {
writer.println(command);
writer.flush();
Thread.sleep(500);
}
/**
* Returns the port of the console defined in the preferences
* @return port
*/
private int getPort() {
IScopeContext context = new InstanceScope();
IEclipsePreferences preferences = context.getNode(OsgiPlugin.PLUGIN_ID);
return Integer.valueOf(preferences.get(OsgiPlugin.PORT_PREFERENCE_KEY,
OsgiPlugin.DEFAULT_PORT));
}
public boolean isCoveredBy(OsgiUpdateJob other) {
return other.symbolicName.equals(symbolicName)
&& other.command.equals(command);
}
public boolean belongsTo(Object family) {
return MODEL_CONTENT_FAMILY == family;
}
/**
* Schedules a update or refresh job for the given bundle
* @param symbolicName the bundle identifier to update
* @param command the command to execute; either refresh or update
*/
public static void schedule(String symbolicName, Command command) {
OsgiUpdateJob job = new OsgiUpdateJob(symbolicName, command);
job.setRule(ResourcesPlugin.getWorkspace().getRoot());
job.setPriority(BUILD);
job.setProperty(IProgressConstants.ICON_PROPERTY,
OsgiUiImages.DESC_OBJS_OSGI);
job.schedule();
}
}