Skip to content

Commit

Permalink
Copy application config file before docker run
Browse files Browse the repository at this point in the history
  • Loading branch information
petrovic-d committed Sep 2, 2024
1 parent db489d1 commit 957334c
Show file tree
Hide file tree
Showing 5 changed files with 338 additions and 138 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.netbeans.modules.cloud.oracle.assets;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.attribute.AclEntry;
import java.nio.file.attribute.AclEntryPermission;
import static java.nio.file.attribute.AclEntryPermission.APPEND_DATA;
import static java.nio.file.attribute.AclEntryPermission.READ_ACL;
import static java.nio.file.attribute.AclEntryPermission.READ_ATTRIBUTES;
import static java.nio.file.attribute.AclEntryPermission.READ_DATA;
import static java.nio.file.attribute.AclEntryPermission.READ_NAMED_ATTRS;
import static java.nio.file.attribute.AclEntryPermission.SYNCHRONIZE;
import static java.nio.file.attribute.AclEntryPermission.WRITE_ACL;
import static java.nio.file.attribute.AclEntryPermission.WRITE_ATTRIBUTES;
import static java.nio.file.attribute.AclEntryPermission.WRITE_DATA;
import static java.nio.file.attribute.AclEntryPermission.WRITE_NAMED_ATTRS;
import java.nio.file.attribute.AclFileAttributeView;
import java.nio.file.attribute.DosFileAttributeView;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFilePermission;
import static java.nio.file.attribute.PosixFilePermission.OWNER_READ;
import static java.nio.file.attribute.PosixFilePermission.OWNER_WRITE;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openide.modules.Places;

/**
*
* @author Dusan Petrovic
*/
public class ConfigFileGenerator {

private static final Logger LOG = Logger.getLogger(ConfigFileGenerator.class.getName());

private static final boolean POSIX = FileSystems.getDefault().supportedFileAttributeViews().contains("posix"); // NOI18N
private static final EnumSet<PosixFilePermission> readWritePosix = EnumSet.of(OWNER_READ, OWNER_WRITE);
private static final EnumSet<PosixFilePermission> readPosix = EnumSet.of(OWNER_READ);

private static final EnumSet<AclEntryPermission> readOnlyAcl = EnumSet.of(
READ_ACL,
READ_ATTRIBUTES,
READ_DATA,
READ_NAMED_ATTRS,
SYNCHRONIZE
);

private static final EnumSet<AclEntryPermission> readWriteAcl = EnumSet.of(
READ_DATA,
WRITE_DATA,
APPEND_DATA,
READ_NAMED_ATTRS,
WRITE_NAMED_ATTRS,
READ_ATTRIBUTES,
WRITE_ATTRIBUTES,
READ_ACL,
WRITE_ACL
);

private final boolean readOnly;
private final String filePrefix;
private final String fileSufix;
private final String configPath;

public ConfigFileGenerator(String filePrefix, String fileSufix, String configPath, boolean readOnly) {
this.readOnly = readOnly;
this.configPath = configPath;
this.filePrefix = filePrefix;
this.fileSufix = fileSufix;
}

public Path writePropertiesFile(Properties props) throws IOException {
Path temp = null;
try {
temp = generateConfigFile();
writePropertiesToFile(props, temp);
} catch (IOException ex) {
deleteTempFile(temp);
throw ex;
}

return temp;
}

private Path generateConfigFile() throws IOException {
Path dir = generateDirPath();

if (!Files.isDirectory(dir, LinkOption.NOFOLLOW_LINKS)) {
Files.createDirectory(dir);
}
if (POSIX) {
return createFilePosix(dir);
}

Path temp = Files.createTempFile(dir, this.filePrefix, this.fileSufix);
setFileOwnerAcl(temp, readWriteAcl);
return temp;
}

private void writePropertiesToFile(Properties props, Path filePath) throws IOException {
try (Writer writer = new FileWriter(filePath.toFile(), Charset.defaultCharset());) {
props.store(writer, "");
if (POSIX) {
setFilePermissionPosix(filePath);
} else {
if (readOnly) {
DosFileAttributeView attribs = Files.getFileAttributeView(filePath, DosFileAttributeView.class);
attribs.setReadOnly(true);
setFileOwnerAcl(filePath, readOnlyAcl);
} else {
setFileOwnerAcl(filePath, readWriteAcl);
}
}
filePath.toFile().deleteOnExit();
}
}

private void setFileOwnerAcl(Path filePath, Set<AclEntryPermission> permissions) throws IOException {
AclFileAttributeView acl = Files.getFileAttributeView(filePath, AclFileAttributeView.class);
AclEntry ownerEntry = findFileOwner(acl);

if (ownerEntry == null) {
throw new IOException("Owner missing, file:" + filePath.toString()); // NOI18N
}

AclEntry ownerAcl = AclEntry.newBuilder(ownerEntry).setPermissions(permissions).build();
acl.setAcl(Collections.singletonList(ownerAcl));
}

private AclEntry findFileOwner(AclFileAttributeView acl) throws IOException {
for(AclEntry e : acl.getAcl()) {
if (e.principal().equals(acl.getOwner())) {
return e;
}
}
return null;
}

private void setFilePermissionPosix(Path temp) throws IOException {
PosixFileAttributeView attributes = Files.getFileAttributeView(temp, PosixFileAttributeView.class);
if (this.readOnly) {
attributes.setPermissions(readPosix);
} else {
attributes.setPermissions(readWritePosix);
}
}


private Path createFilePosix(Path dir) throws IOException {
FileAttribute<?> readWriteAttribs = PosixFilePermissions.asFileAttribute(readWritePosix);
return Files.createTempFile(dir,this.filePrefix, this.fileSufix, readWriteAttribs);
}

private Path generateDirPath() {
File file = Places.getCacheSubdirectory(this.configPath);
file.deleteOnExit();
return file.toPath();
}

private void deleteTempFile(Path temp) {
if (temp != null && Files.isRegularFile(temp, LinkOption.NOFOLLOW_LINKS)) {
try {
if (POSIX) {
PosixFileAttributeView attribs = Files.getFileAttributeView(temp, PosixFileAttributeView.class);
attribs.setPermissions(readWritePosix);
} else {
DosFileAttributeView attribs = Files.getFileAttributeView(temp, DosFileAttributeView.class);
attribs.setReadOnly(false);
}
Files.delete(temp);
} catch (IOException ex) {
LOG.log(Level.WARNING, "deleteTempFile", ex);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.netbeans.modules.cloud.oracle.assets;

import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import org.netbeans.spi.lsp.CommandProvider;
import org.openide.util.lookup.ServiceProvider;

/**
*
* @author Dusan Petrovic
*/
@ServiceProvider(service = CommandProvider.class)
public class ConfigFileProvider implements CommandProvider {
private static final String GET_CONFIG_FILE_PATH = "nbls.config.file.path"; //NOI18N

private final ConfigFileGenerator applicationPropertiesFileGenerator;
private final ConfigFileGenerator bootstrapPropertiesFileGenerator;

public ConfigFileProvider() {
this.applicationPropertiesFileGenerator = new ConfigFileGenerator("application-", ".properties", GET_CONFIG_FILE_PATH, false); // NOI18N
this.bootstrapPropertiesFileGenerator = new ConfigFileGenerator("bootstrap-", ".properties", GET_CONFIG_FILE_PATH, false); // NOI18N
}

@Override
public Set<String> getCommands() {
return Collections.singleton(GET_CONFIG_FILE_PATH);
}

@Override
public CompletableFuture<Object> runCommand(String command, List<Object> arguments) {
CompletableFuture ret = new CompletableFuture();

Properties applicationProps = new Properties();
Properties bootstrapProps = new Properties();
PropertiesGenerator propGen = new PropertiesGenerator(false);

applicationProps.putAll(propGen.getApplication());
bootstrapProps.putAll(propGen.getBootstrap());

String applicationPropertiesPath = null;
String bootstrapPropertiesPath = null;
try {
if (!bootstrapProps.isEmpty()) {
Path bootstrapProperties = bootstrapPropertiesFileGenerator.writePropertiesFile(bootstrapProps);
bootstrapPropertiesPath = bootstrapProperties.toAbsolutePath().toString();
}

if (!applicationProps.isEmpty()) {
Path applicationProperties = applicationPropertiesFileGenerator.writePropertiesFile(applicationProps);
applicationPropertiesPath = applicationProperties.toAbsolutePath().toString();
}
ret.complete(new ConfigFilesResponse(applicationPropertiesPath, bootstrapPropertiesPath));
} catch (IOException ex) {
ret.completeExceptionally(ex);
return ret;
}

return ret;
}

private class ConfigFilesResponse {

final String applicationProperties;
final String bootstrapProperties;

public ConfigFilesResponse(String applicationProperties, String bootstrapProperties) {
this.applicationProperties = applicationProperties;
this.bootstrapProperties = bootstrapProperties;
}
}
}
Loading

0 comments on commit 957334c

Please sign in to comment.