/**
* Licensed to the Austrian Association for Software Tool Integration (AASTI)
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. The AASTI 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.openengsb.connector.virtual.filewatcher.internal;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import org.apache.commons.lang.ArrayUtils;
import org.openengsb.connector.usernamepassword.Password;
import org.openengsb.connector.virtual.filewatcher.FileSerializer;
import org.openengsb.core.api.Event;
import org.openengsb.core.api.EventSupport;
import org.openengsb.core.api.context.ContextHolder;
import org.openengsb.core.api.security.AuthenticationContext;
import org.openengsb.core.common.VirtualConnector;
import org.openengsb.core.ekb.api.EKBCommit;
import org.openengsb.core.ekb.api.PersistInterface;
import org.openengsb.core.ekb.api.QueryInterface;
public class FileWatcherConnector extends VirtualConnector implements EventSupport {
private Class<?> modelType;
private QueryInterface queryService;
private PersistInterface persistService;
private FileSerializer<?> fileSerializer;
private File watchfile;
private AuthenticationContext authenticationContext;
private List<?> localModels = new ArrayList<Object>();
private Timer timer;
public FileWatcherConnector(String instanceId, String domainType, PersistInterface persistService,
QueryInterface queryService, AuthenticationContext authenticationContext) {
super(instanceId, domainType);
this.authenticationContext = authenticationContext;
this.persistService = persistService;
this.queryService = queryService;
}
@Override
protected Object doInvoke(Object proxy, Method method, Object[] args) throws Throwable {
if (ArrayUtils.contains(this.getClass().getInterfaces(), method.getDeclaringClass())) {
return method.invoke(this, args);
}
return null;
}
@Override
public void onEvent(Event event) {
try {
update();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private synchronized void update() throws IOException {
List<?> models = queryService.queryForActiveModels(modelType);
if (models == null) {
watchfile.delete();
localModels = Collections.emptyList();
} else {
fileSerializer.writeFile(watchfile, (List) models);
localModels = models;
}
}
private static <ModelType> EKBCommit buildCommit(List<ModelType> localModels, List<ModelType> newModels) {
EKBCommit result = new EKBCommit();
List<ModelType> inserted = subtract(newModels, localModels);
result.addInserts(inserted);
List<ModelType> deleted = subtract(localModels, newModels);
result.addDeletes(deleted);
return result;
}
private static <ModelType> List<ModelType> subtract(List<ModelType> list1, List<ModelType> list2) {
ArrayList<ModelType> result = new ArrayList<ModelType>(list1);
result.removeAll(list2);
return result;
}
public void setFileSerializer(FileSerializer<?> fileSerializer) {
this.fileSerializer = fileSerializer;
}
public void setLocalModels(List<?> localModels) {
this.localModels = localModels;
}
public void setModelType(Class<?> modelType) {
this.modelType = modelType;
}
public void setWatchfile(File watchfile) {
if (!watchfile.getParentFile().exists()) {
watchfile.getParentFile().mkdirs();
}
this.watchfile = watchfile;
try {
initFilePoller();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void initFilePoller() throws IOException {
if (timer != null) {
timer.cancel();
}
timer = new Timer();
DirectoryWatcher watcher = new DirectoryWatcher(watchfile) {
@Override
protected synchronized void onFileModified() {
List<?> newModels = null;
try {
newModels = fileSerializer.readFile(watchfile);
} catch (IOException e) {
throw new RuntimeException(e);
}
EKBCommit commit = buildCommit((List) localModels, (List) newModels);
commit.setConnectorId("filewatcher");
commit.setInstanceId(instanceId);
commit.setDomainId(domainType);
ContextHolder.get().setCurrentContextId("foo");
authenticationContext.login("admin", new Password("password"));
persistService.commit(commit);
authenticationContext.logout();
}
};
if (watchfile.exists()) {
localModels = fileSerializer.readFile(watchfile);
} else {
localModels = Collections.emptyList();
}
timer.schedule(watcher, 0, 1000);
}
}