/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates.
*
* 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.kie.workbench.common.screens.server.management.backend.storage;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import com.thoughtworks.xstream.XStream;
import org.kie.server.controller.api.model.spec.ServerTemplate;
import org.kie.server.controller.api.model.spec.ServerTemplateKey;
import org.kie.server.controller.api.storage.KieServerTemplateStorage;
import org.kie.workbench.common.screens.server.management.backend.storage.migration.ServerTemplateMigration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.uberfire.io.IOService;
import org.uberfire.java.nio.file.FileSystem;
import org.uberfire.java.nio.file.NotDirectoryException;
import org.uberfire.java.nio.file.Path;
@ApplicationScoped
public class ServerTemplateVFSStorage implements KieServerTemplateStorage {
private static final Logger logger = LoggerFactory.getLogger(ServerTemplateVFSStorage.class);
private IOService ioService;
private FileSystem fileSystem;
private final XStream xs = new XStream();
//enable proxy
public ServerTemplateVFSStorage() {
}
@Inject
public ServerTemplateVFSStorage( @Named("configIO") final IOService ioService, @Named("systemFS") final FileSystem fileSystem ) {
this.ioService = ioService;
this.fileSystem = fileSystem;
}
@PostConstruct
public void init() {
ServerTemplateMigration.migrate(buildPath(null), ioService, xs, this);
}
@Override
public ServerTemplate store( final ServerTemplate serverTemplate ) {
logger.debug("About to store server template {}", serverTemplate);
final Path path = buildPath( serverTemplate.getId() );
if (!ioService.exists(path)) {
try {
ioService.startBatch(path.getFileSystem());
ioService.write(path, xs.toXML(serverTemplate));
} finally {
ioService.endBatch();
}
logger.debug("Server template {} stored successfully");
return serverTemplate;
} else {
throw new IllegalArgumentException("Server template with id " + serverTemplate.getId() + " is already stored");
}
}
@Override
public List<ServerTemplateKey> loadKeys() {
logger.debug("About to load all available server templates (as keys only)...");
final List<ServerTemplateKey> result = new ArrayList<ServerTemplateKey>();
final Path dir = buildPath( null );
try {
ioService.startBatch( dir.getFileSystem() );
for ( final Path registeredServer : ioService.newDirectoryStream( dir ) ) {
try {
ServerTemplate serverTemplate = readServerTemplate(registeredServer);
logger.debug("Found server template {}, taking its short key version...");
result.add( new ServerTemplateKey(serverTemplate.getId(), serverTemplate.getName()) );
} catch ( final Exception ignore ) {
ioService.delete( registeredServer );
}
}
logger.debug("All found server template keys {}", result);
return result;
} catch ( final NotDirectoryException ignore ) {
logger.debug("No directory found {}, returning empty result", dir);
return result;
} finally {
ioService.endBatch();
}
}
@Override
public List<ServerTemplate> load() {
logger.debug("About to load all available server templates...");
final List<ServerTemplate> result = new ArrayList<ServerTemplate>();
final Path dir = buildPath( null );
try {
ioService.startBatch( dir.getFileSystem() );
for ( final Path registeredServer : ioService.newDirectoryStream( dir ) ) {
try {
ServerTemplate serverTemplate = readServerTemplate(registeredServer);
logger.debug("Found server template {}", serverTemplate);
result.add( serverTemplate );
} catch ( final Exception ignore ) {
ioService.delete( registeredServer );
}
}
logger.debug("All found server templates {}", result);
return result;
} catch ( final NotDirectoryException ignore ) {
logger.debug("No directory found {}, returning empty result", dir);
return result;
} finally {
ioService.endBatch();
}
}
@Override
public ServerTemplate load( final String identifier ) {
logger.debug("About to load server template for {}", identifier);
final Path path = buildPath( identifier );
ServerTemplate serverTemplate = readServerTemplate(path);
logger.debug("Server template loaded {}", serverTemplate);
return serverTemplate;
}
@Override
public boolean exists( final String identifier ) {
boolean serverTemplateExists = ioService.exists( buildPath( identifier));
logger.debug("Server with id {} exists = {}", identifier, serverTemplateExists);
return serverTemplateExists;
}
@Override
public ServerTemplate update( final ServerTemplate serverTemplate ) {
logger.debug("About to update server template {}", serverTemplate);
final Path path = buildPath( serverTemplate.getId() );
try {
ioService.startBatch(path.getFileSystem());
ioService.write(path, xs.toXML(serverTemplate));
} finally {
ioService.endBatch();
}
logger.debug("Server template {} updated successfully", serverTemplate);
return serverTemplate;
}
@Override
public ServerTemplate delete( final String identifier ) {
logger.debug("About to remove server template with id {}", identifier);
final Path path = buildPath( identifier );
ServerTemplate serverTemplate = null;
try {
ioService.startBatch( path.getFileSystem() );
serverTemplate = readServerTemplate(path);
ioService.delete( path );
} finally {
ioService.endBatch();
}
logger.debug("Server template with id {}, removed successfully", identifier);
return serverTemplate;
}
/*
* helper methods
*/
protected ServerTemplate readServerTemplate(final Path registeredServer) {
try {
if (ioService.exists(registeredServer)) {
final ServerTemplate serverTemplate = (ServerTemplate) xs.fromXML(ioService.readAllString(registeredServer));
return serverTemplate;
}
} catch ( Exception ex ) {
logger.error("Error reading KieServerInstance definition from path {}", registeredServer, ex);
}
return null;
}
protected Path buildPath( final String identifier ) {
if ( identifier != null ) {
return fileSystem.getPath( "servers", "remote", toHex( identifier ) + "-template.xml" );
} else {
return fileSystem.getPath( "servers", "remote" );
}
}
protected String toHex( final String arg ) {
if ( isHex( arg ) ) {
return arg;
}
return String.format( "%x", new BigInteger( 1, arg.toLowerCase().getBytes( Charset.forName("UTF-8") ) ) );
}
protected boolean isHex( final String endpoint ) {
try {
new BigInteger( endpoint, 16 );
return true;
} catch ( NumberFormatException ex ) {
return false;
}
}
}