/*
* (C) Copyright 2006-2010 Nuxeo SA (http://nuxeo.com/) and others.
*
* 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.
*
* Contributors:
* bstefanescu
*/
package org.nuxeo.ecm.automation.client.jaxrs.spi;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import org.nuxeo.ecm.automation.client.AdapterFactory;
import org.nuxeo.ecm.automation.client.AdapterManager;
import org.nuxeo.ecm.automation.client.AutomationClient;
import org.nuxeo.ecm.automation.client.LoginCallback;
import org.nuxeo.ecm.automation.client.LoginInfo;
import org.nuxeo.ecm.automation.client.Session;
/**
* Abstract class for clients running on real JVMs.
* <p>
* When your implementation is designed for running in environment that supports limited Java API like GWT or portable
* devices you may need to directly implement the {@link AutomationClient} interface.
*
* @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
*/
public abstract class JavaClient implements AutomationClient {
protected String url;
protected AdapterManager adapters;
protected ExecutorService async;
protected JavaClient(String url) {
this(url, null);
}
public JavaClient(String url, ExecutorService executor) {
this.url = url.endsWith("/") ? url : url + "/";
this.async = executor == null ? Executors.newCachedThreadPool(new ThreadFactory() {
public Thread newThread(Runnable r) {
return new Thread("AutomationAsyncExecutor");
}
}) : executor;
}
/**
* Validate the credentials. The login must occurs in first place before a session is created. A stateless session
* may login each time using these credentials but you canot get a session without login-in first.
*
* @param username
* @param password
* @return
*/
protected abstract LoginInfo login(String username, String password);
/**
* Create a valid session using the authenticated login. The session will download any required data like the
* operation registry before being usable.
*
* @param login
* @return
*/
protected abstract JavaSession createSession(LoginInfo login);
@Override
public String getBaseUrl() {
return url;
}
public AdapterManager getAdapterManager() {
return adapters;
}
public void asyncExec(Runnable runnable) {
async.execute(runnable);
}
@Override
public <T> T getAdapter(Session session, Class<T> adapterType) {
return adapters.getAdapter(session, adapterType);
}
@Override
public void registerAdapter(AdapterFactory<?> factory) {
adapters.registerAdapter(factory);
}
@Override
public Session getSession(LoginCallback cb) {
String[] login = cb.getLogin();
return getSession(login[0], login[1]);
}
@Override
public Session getSession(String username, String password) {
LoginInfo login = login(username, password);
if (login == null) {
throw new RuntimeException("Failed to login as " + username);
}
return createSession(login);
}
@Override
public Session getSession() {
return getSession((String) null, (String) null);
}
@Override
public void shutdown() {
shutdown(500);
}
/**
* TODO Move this in interface?
*
* @param timeout
*/
public void shutdown(long timeout) {
try {
async.awaitTermination(timeout, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// do nothing - TODO: log?
} finally {
async = null;
url = null;
adapters = null;
}
}
}