How to use appProperties in Google Drive api v3? - java

How to set the app properties of a file using Google Drive v3 in java?
The reference says: "files.update with {'appProperties':{'key':'value'}}", but I don't understand how to apply that to my java code.
I've tried things like
file = service.files().create(body).setFields("id").execute();
Map<String, String> properties = new HashMap<>();
properties.put(DEVICE_ID_KEY, deviceId);
file.setAppProperties(properties);
service.files().update(file.getId(), file).setFields("appProperties").execute();
but then I get an error that "The resource body includes fields which are not directly writable."
And to get the data:
File fileProperty = service.files().get(sFileId).setFields("appProperties").execute();
So how to set and get the properties for the file?
Thanks! :)
Edit
I tried
file = service.files().create(body).setFields("id").execute();
Map<String, String> properties = new HashMap<>();
properties.put(DEVICE_ID_KEY, deviceId);
file.setAppProperties(properties);
service.files().update(file.getId(), file).execute();
but I still get the same error message.

To avoid this error on v3
"The resource body includes fields which are not directly writable."
when calling update, you need to create an empty File with the new changes and pass that to the update function.
I wrote this and other notes as a v3 Migration Guide here.

The Drive API client for Java v3 indicates that the File.setAppProperties will require a Hashmap<String,String> parameter. Try to remove the setFields("appProperties") call since you are trying to overwrite appProperties itself (you're still calling Update at this time).
When retrieving appProperties, you'll just need to call getAppProperties.
Hope this helps!

File fileMetadata = new File();
java.io.File filePath = new java.io.File(YOUR_LOCAL_FILE_PATH);
Map<String, String> map = new HashMap<String, String>();
map.put(YOUR_KEY, YOUR_VALUE); //can be filled with custom String
fileMetadata.setAppProperties(map);
FileContent mediaContent = new FileContent(YOUR_IMPORT_FORMAT, filePath);
File file = service.files().create(fileMetadata, mediaContent)
.setFields("id, appProperties").
.execute();
YOUR_IMPORT_FORMAT, fill this with the value in this link, https://developers.google.com/drive/api/v3/manage-uploads, there is explanation below the example code
setFields("id, appProperties"), fill this with the value in this link: https://developers.google.com/drive/api/v3/migration, this the most important part I think, if you don't set the value in the setFields method your additional input will not be written

With version v3, to add or update appProperties for an existing file and without this error:
"The resource body includes fields which are not directly writable."
You should do:
String fileId = "Your file id key here";
Map<String, String> appPropertiesMap = new HashMap<String, String>();
appPropertiesMap.put("MyKey", "MyValue");
appPropertiesMap.put("MySecondKey", "any value");
//set only the metadata you want to change
//do not set "id" !!! You will have "The resource body includes fields which are not directly writable." error
File fileMetadata = new File();
fileMetadata.setAppProperties(appPropertiesMap);
File updatedFileMetadata = driveService.files().update(fileId, fileMetadata).setFields("id, appProperties").execute();
System.out.printf("Hey, I see my appProperties :-) %s \n", updatedFileMetadata.toPrettyString());

Related

how to use java to set "ACL" to all files under google storage folder

I want to change all files in folder over GCP to be publicly shared.
I see how to do this via gsutils.
How can i do this via java api?
Here is my try:
public static void main(String[] args) throws Exception {
//// more setting up code here...
GoogleCredential credential = GoogleCredential.fromStream(credentialsStream, httpTransport, jsonFactory);
credential = credential.createScoped(StorageScopes.all());
final Storage storage = new Storage.Builder(httpTransport, jsonFactory, credential)
.setApplicationName("monkeyduck")
.build();
final Storage.Objects.Get getRequest1 = storage.objects().get(bucketName, "sounds/1.0/arabic_test22/1000meters.mp3");
final StorageObject object1 = getRequest1.execute();
System.out.println(object1);
final List<ObjectAccessControl> aclList = new ArrayList<>();
// final ObjectAccessControl acl = new ObjectAccessControl()
// .setRole("PUBLIC-READER")
// .setProjectTeam(new ObjectAccessControl.ProjectTeam().setTeam("viewers"));
final ObjectAccessControl acl = new ObjectAccessControl()
.setRole("READER").setEntity("allUsers");
//System.out.println(acl);
aclList.add(acl);
object1.setAcl(aclList);
final Storage.Objects.Insert insertRequest = storage.objects().insert(bucketName, object1);
insertRequest.getMediaHttpUploader().setDirectUploadEnabled(true);
insertRequest.execute();
}
}
I get NPE because insertRequest.getMediaHttpUploader() == null
Instead of using objects().insert(), try using the ACL API
ObjectAccessControl oac = new ObjectAccessControl()
oac.setEntity("allUsers")
oac.setRole("READER");
Insert insert = service.objectAccessControls().insert(bucketName, "sounds/1.0/arabic_test22/1000meters.mp3", oac);
insert.execute();
About the folder matter. In Cloud Storage the concept of "folder" does not exists, it is only "bucket" and "object name".
The fact you can see the file grouped inside folders (I'm talking about the Cloud Storage Browser) it is only a graphic representation. With the API you will always handle "bucket" and "object name".
Knowing this, the Objects: list provides a prefix parameter which you can use to filter all the objects where the name starts with it. If you think the start of your object name as the folder, this filter can achieve what you're looking for.
From the documentation of the API I quote
In conjunction with the prefix filter, the use of the delimiter
parameter allows the list method to operate like a directory listing,
despite the object namespace being flat. For example, if delimiter
were set to "/", then listing objects from a bucket that contains the
objects "a/b", "a/c", "d", "e", "e/f" would return objects "d" and
"e", and prefixes "a/" and "e/".

Java: Read Line From File Based on Start of Line

I know how to read from file using Java. What I want to do is read a specific line which starts with specific text.
What I plan on doing is storing certain program settings in a txt file so I can retrieve them quickly when I exit/restart program.
For example, the file may look something like this:
First Name: John
Last Name: Smith
Email: JohnSmith#gmail.com
Password: 123456789
The : would be the delimiter and in the program I want to be able to retrieve specific values based on the "key" (such as "First Name", "Last Name" and so on).
I know I could store it to DB but I want to write it quickly to test my program without going through hassle of writing it to DB.
Have a look at java.util.Properties. It does everything you ask for here, including parsing the file.
example code:
File file = new File("myprops.txt");
Properties properties = new Properties();
try (InputStream in = new FileInputStream (file)) {
properties.load (in);
}
String myValue = (String) properties.get("myKey");
System.out.println (myValue);
Note: if you want to use a space in your property key, you have to escape it. For example:
First\ Name: Stef
Here is documentation about the syntax of the properties file.
What I want to do is read a specific line which starts with specific text.
Read from the start of the file, skipping all the lines you don't need. There is no simpler way. You can index you file for fast access, but you have scan the file at least once.
You can use Properties to retrieve both key and value from file.
Reading data from text file using Properties class
File file = new File("text.txt");
FileInputStream fileInput = new FileInputStream(file);
Properties properties = new Properties();
properties.load(fileInput);
fileInput.close();
Enumeration enuKeys = properties.keys();
while (enuKeys.hasMoreElements()) {
String key = (String) enuKeys.nextElement();
String value = properties.getProperty(key);//with specific key
System.out.println(key + ": " + value);//both key and value
}
You can retrieve specific value based on the key.
System.out.println(properties.getProperty("Password"));//with specific key
With Java 8, you can also read your file into a map this way:
Map<String, String> propertiesMap = Files.lines(Paths.get("test.txt")) // read in to Stream<String>
.map(x -> x.split(":\\s+")) // split to Stream<String[]>
.filter(x->x.length==2) // only accept values which consist of two values
.collect(Collectors.toMap(x -> x[0], x -> x[1])); // create map. first element or array is key, second is value

Setting/Updating multiple document properties in SharePoint 2010 using OpenCMIS

Have tried to search for this almost 'everywhere', but couldn't find a pointer as to how to implement this. Please kindly review my code and offer suggestions on how to set/update ALL documents properties in SharePoint using OpenCMIS. Have created the documents successfully using CMIS, however I'm not able to populate different values for different documents.
For example, a.pdf, b.pdf have different properties. So when I update them, i expect the value to be mapped from array of values assigned to them but at the moment, the same value are being append to all the documents...
Please see my code below, hopefully it will make things clearer:
try {
String [] nextLine =null;
CSVReader reader = new CSVReader(new FileReader(indexFileLocation));
List content = reader.readAll();
for (Object o : content) {
nextLine = (String[]) o;
System.out.println("\n"+ nextLine[2] + "\n"+nextLine[7] + "\n"+ nextLine[6]);
}
//reader.close();
Map <String, Object> newDocProps = new HashMap<String, Object>();
newDocProps.put(PropertyIds.OBJECT_TYPE_ID, "cmis:document");
newDocProps.put(PropertyIds.NAME, ff.getName());
Document doc = newFolder.createDocument(newDocProps, contentStream, VersioningState.NONE);
CmisObject cmisobject = (Document) session.getObject(doc.getId());
Map<String, Object> pp = new HashMap<String, Object>();
//pp.put(PropertyIds.OBJECT_ID, "Name");
pp.put("WorkflowNumber", nextLine[7]);
pp.put("InvoiceDate", nextLine[2]);
cmisobject.updateProperties(pp);
Any help is appreciated.
#Albert, How are you creating session? It could be an issue with session creation. Please paste your code here to create session.

Amazon S3 upload file and get URL

Is it possible to upload a txt/pdf/png file to Amazon S3 in a single action, and get the uploaded file URL as the response?
If so, is AWS Java SDK the right library that I need to add in my java struts2 web application?
Please suggest me a solution for this.
No you cannot get the URL in single action but two :)
First of all, you may have to make the file public before uploading because it makes no sense to get the URL that no one can access. You can do so by setting ACL as Michael Astreiko suggested.
You can get the resource URL either by calling getResourceUrl or getUrl.
AmazonS3Client s3Client = (AmazonS3Client)AmazonS3ClientBuilder.defaultClient();
s3Client.putObject(new PutObjectRequest("your-bucket", "some-path/some-key.jpg", new File("somePath/someKey.jpg")).withCannedAcl(CannedAccessControlList.PublicRead))
s3Client.getResourceUrl("your-bucket", "some-path/some-key.jpg");
Note1:
The different between getResourceUrl and getUrl is that getResourceUrl will return null when exception occurs.
Note2:
getUrl method is not defined in the AmazonS3 interface. You have to cast the object to AmazonS3Client if you use the standard builder.
You can work it out for yourself given the bucket and the file name you specify in the upload request.
e.g. if your bucket is mybucket and your file is named myfilename:
https://mybucket.s3.amazonaws.com/myfilename
The s3 bit will be different depending on which region your bucket is in. For example, I use the south-east asia region so my urls are like:
https://mybucket.s3-ap-southeast-1.amazonaws.com/myfilename
For AWS SDK 2+
String key = "filePath";
String bucketName = "bucketName";
PutObjectResponse response = s3Client
.putObject(PutObjectRequest.builder().bucket(bucketName ).key(key).build(), RequestBody.fromFile(file));
GetUrlRequest request = GetUrlRequest.builder().bucket(bucketName ).key(key).build();
String url = s3Client.utilities().getUrl(request).toExternalForm();
#hussachai and #Jeffrey Kemp answers are pretty good. But they have something in common is the url returned is of virtual-host-style, not in path style. For more info regarding to the s3 url style, can refer to AWS S3 URL Styles. In case of some people want to have path style s3 url generated. Here's the step. Basically everything will be the same as #hussachai and #Jeffrey Kemp answers, only with one line setting change as below:
AmazonS3Client s3Client = (AmazonS3Client) AmazonS3ClientBuilder.standard()
.withRegion("us-west-2")
.withCredentials(DefaultAWSCredentialsProviderChain.getInstance())
.withPathStyleAccessEnabled(true)
.build();
// Upload a file as a new object with ContentType and title specified.
PutObjectRequest request = new PutObjectRequest(bucketName, stringObjKeyName, fileToUpload);
s3Client.putObject(request);
URL s3Url = s3Client.getUrl(bucketName, stringObjKeyName);
logger.info("S3 url is " + s3Url.toExternalForm());
This will generate url like:
https://s3.us-west-2.amazonaws.com/mybucket/myfilename
Similarly if you want link through s3Client you can use below.
System.out.println("filelink: " + s3Client.getUrl("your_bucket_name", "your_file_key"));
a bit old but still for anyone stumbling upon this in the future:
you can do it with one line assuming you already wrote the CredentialProvider and the AmazonS3Client.
it will look like this:
String ImageURL = String.valueOf(s3.getUrl(
ConstantsAWS3.BUCKET_NAME, //The S3 Bucket To Upload To
file.getName())); //The key for the uploaded object
and if you didn't wrote the CredentialProvider and the AmazonS3Client then just add them before getting the URL like this:
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
getApplicationContext(),
"POOL_ID", // Identity pool ID
Regions.US_EAST_1 // Region
);
Below method uploads file in a particular folder in a bucket and return the generated url of the file uploaded.
private String uploadFileToS3Bucket(final String bucketName, final File file) {
final String uniqueFileName = uploadFolder + "/" + file.getName();
LOGGER.info("Uploading file with name= " + uniqueFileName);
final PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, uniqueFileName, file);
amazonS3.putObject(putObjectRequest);
return ((AmazonS3Client) amazonS3).getResourceUrl(bucketName, uniqueFileName);
}
If you're using AWS-SDK, the data object returned contains the Object URL in data.Location
const AWS = require('aws-sdk')
const s3 = new AWS.S3(config)
s3.upload(params).promise()
.then((data)=>{
console.log(data.Location)
})
.catch(err=>console.log(err))
System.out.println("Link : " + s3Object.getObjectContent().getHttpRequest().getURI());
With this code you can retrieve the link of already uploaded file to S3 bucket.
To make the file public before uploading you can use the #withCannedAcl method of PutObjectRequest:
myAmazonS3Client.putObject(new PutObjectRequest('some-grails-bucket', 'somePath/someKey.jpg', new File('/Users/ben/Desktop/photo.jpg')).withCannedAcl(CannedAccessControlList.PublicRead))
String url = myAmazonS3Client.getUrl('some-grails-bucket', 'somePath/someKey.jpg').toString();

How to pass multiple parameters to reports and export to PDF in JasperReports from Java

I'm trying to use Jasper Reports to help with reporting in my application. I will have to display my reports in HTML (JSP) and would also need to be able to export the reports to PDF from within my web page.
Most of my reports require multiple parameters, and I can't figure out how to pass them from my Servlet (if I have to pass them there) to the report.
P.S: I'm not using frameworks of any sort, it would be great if you could suggest a framework free implementation.
you can use HashMap like
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("parameterName","value");
JasperPrint print = JasperFillManager.fillReport(report,map,con);
//Preparing data - change this as per your requirement
List<DataDTO> dataDTOList = new ArrayList<DataDTO>();
DataDTO dataDTO = new DataDTO;
dataDTO.setFirstName("FirstName"); // in your Jasper field name is 'firstName' as type String
dataDTO.setLastName("LastName"); // in your Jasper field name is 'lastName' as type String
dataDTOList.add(dataDTO);
// Adding data
JRDataSource jrdatasource = new JRBeanCollectionDataSource(dataDTOList);
// Exporting report
File jasperFile = new File("C:/YourReport.jasper"); // change this
JasperReport jasperReport = (JasperReport) JRLoader.loadObject(new FileInputStream(jasperFile.getAbsolutePath()));
Map parameters = new HashMap();
JRConcurrentSwapFile jrSwapFile = new JRConcurrentSwapFile("C:/PDFOutput/"),30,2);
JRSwapFileVirtualizer virtualizer = new JRSwapFileVirtualizer(2,jrSwapFile,true);
parameters.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
JasperPrint jpPrintObj = JasperFillManager.fillReport(jasperReport,parameters,jrdatasource);
JasperExportManager.exportReportToPdfFile(jpPrintObj,"C:/PDFOutput/");`
This example will help you, it doesn't require any framework. It exports the report as a PDF. And you can use map as Anil had already explained
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("parameterName","value");
map.put("parameterName2","value2");
map.put("parameterName3","value3");
JasperPrint print = JasperFillManager.fillReport(report,map,con);
to pass multiple parameters.

Categories

Resources